1

I'm trying to subclass primitive types in Python like this (simplified version):

class MyInt(int):
    pass

I thought that an object of this class would take the same amount of memory as the primitive one. But, apparently, that's not true:

import sys
sys.getsizeof(10)          # 24
sys.getsizeof(MyInt(10))   # 72

Using __slots__, I was able to save some memory, but the subclass still takes more space:

class MyInt(int):
    __slots__ = ()


sys.getsizeof(10)          # 24
sys.getsizeof(MyInt(10))   # 56

If I subclass my own classes, on the other hand, the memory usage is the same:

class Father(object):
    pass


class Son(Father):
    pass

sys.getsizeof(Father())  # 64
sys.getsizeof(Son())     # 64
  1. Why does the subtype object use more memory than the primitive type object, if there are no extra fields?
  2. Is there a way to prevent (or minimize) this?

I'm using Python 2.7.12.

7
  • One way to reduce memory consumption in general is the "Flyweight Pattern" a.k.a. "interning" of values. In Python, you can overload __new__ and look up the instance in a dictionary instead of creating a new one. Commented Jan 31, 2019 at 16:24
  • 4
    In python3, there will not be a difference in size if you force slots to be empty. Commented Jan 31, 2019 at 16:29
  • 1
    An instance of a user-defined class still has things like a list of its base classes, which occupies memory. Why are you defining MyInt in the first place? Commented Jan 31, 2019 at 16:34
  • 1
    as a general rule subclassing built-in types is seldom a good idea - composition / delegation is usually a better solution. Commented Jan 31, 2019 at 16:48
  • @chepner I want to create value objects (in DDD sense) to represent concepts like, for instance, a product ID, product price, and so on. A product ID is not an int, it's a subset of an int, because only integers greater than zero are valid IDs. These types would encapsulate these rules. Commented Jan 31, 2019 at 16:51

1 Answer 1

1

Subclassing built-in classes was only possible in Python when "new style classes" were created in Python 2.2. So, without looking at the code, or reading carefully the presentation notes at this Guido's article, it is possible to infer that some boilerplate internal fields are needed in Python2 to allow built-in classes (which had their code base written prior to the unification) to work and behave well as "user defined classes" when subclassed. (That is "object" behavior that is not built-in the code base for "old-style" "int" objects).

Whatever takes place is somewhere inside Python's 2.7 Objects/typeobject.c - so you may take a look there (or wait until someone who can more easily analyse that come up with another answer)

That, as @blownhither_ma mentions in the comments above, seems not to be the case in Python3 anymore - I'd say the class unification have been consolidated since 2009:

In [158]: from sys import getsizeof as sizeof

In [159]: sizeof(int())
Out[159]: 24

In [160]: class MInt(int):
     ...:     __slots__ = ()
     ...:     

In [161]: sizeof(MInt())
Out[161]: 24

So, while there are things yet to be answered on your question, they matter only for Python 2, which no one should be using in new code by now.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.