Chuck,
Python is huge already and keeps growing so there can be very long discussions especially on a not-yet well-defined need.
Adding a dunder method is fairly straightforward. Your object may only happen to have data aspects now, but can have all kinds of methods defined including defining one called sizeof() containing two leading and trailing underscores. How you implement it is up to you but a straightforward method would sequentially keep adding the sizes of the constituents (some may need recursive searches) and return the sum plus perhaps some padding representing the space the object framework uses. If the contents are fixed and won’t change, this can be computed once when the object is created and the result stored, or computed only the first time and stored for subsequent needs and so on. Other approaches may use the internal dictionary to loop on and find what internal sub-objects are available and check their sizes.
I note in some cases, especially in other languages, there are cases where objects or parts of them are shared. An example might be if a dataframe-like object gets changes in one column, to make a new dataframe-like object, and both still exist as valid objects, the remaining columns may be kept in common but in a way that carefully deals with what happens later if one of them makes further changes and so on. This can happen invisibly in languages like R and it may be there are objects you have with similar behavior. So, in building or modifying your custom class, there may be places you want to copy or deep copy so that you can be sure that any storage you are measuring is unique and freeing the object can release all the memory.
And note that often some things are intrinsically shared and there may actually be a memory location containing constants like the digit 1 or “Hello World!” that may not occupy more space when placed in one or more of your class instances other than the “pointer” to them. And, if all your objects share some data, there are many choices in python that allow the data to be stored in more convenient ways including sometimes the class itself as a static part.
My point is not to depend on any sizes you get to be exactly what you think. What you may get is the maximum size a collection of your class instances contains. But taken as a whole, the entire collection of instances of the class can occupy less space. You may benefit from choosing data types that use less space if your data will fit. Sometimes multiple items can be combined for storage and extracted as needed, such as storing lots of Boolean flags into a single character or integer. Speaking of which, python integers can get very large and use more space as needed.
And, if space is a constraint, there are many tradeoffs to consider. For example, how much space does a dictionary use for just 5 items versus some different processing that searches another kind of data structure like a tuple of tuples or just a series of if statements that search and return the values directly. Compact can be a tradeoff for slow.
I did not see any explanation of why you need the info, and that is fine, but if you know the details of when and why you might need to determine such sizes, you may be able to tune the work you do to get it done fast in programmer time, or to have it be efficient in time or space as it runs or even to realize some other approach is what you really need such as compression of text or storing some of the data in a common external area that allows sharing.
Avi