2
class Player:
    # __slots__ = ['name','age','gsnum']
    def __init__(self,name,age,gsnum):
        self.name = name
        self.age = age
        self.gsnum = gsnum

I defined this class, with three attributes

when using __slots__ to save memory:

I get 36 for one instance (sys.getsizeof()) if not using the __slots__, I still get 36 as the memory size,

What's the problem here? 32bit Python 2.7

chthonicdaemon
  • 19,180
  • 2
  • 52
  • 66
Eric Wang
  • 21
  • 2
  • It looks like you commented out the slots declaration. – Kevin May 04 '16 at 04:38
  • On my machine using `__slots__` for this example *increases* memory usage. – Bakuriu May 04 '16 at 04:45
  • Is memory really a problem? Note that since python3.3 with the introduction of PEP 412 instances are able to share part of their `dict`s and thus the overhead for `dict`s per instance was significantly reduced. – Bakuriu May 04 '16 at 04:52
  • @Bakuriu thanks, I didn't know that. Well, I just remembered this, I don't think it's a big deal either, but the results are the opposite – Eric Wang May 04 '16 at 05:05

1 Answers1

5

The Python Documentation states that:

The default can be overridden by defining __slots__ in a new-style class definition. The __slots__ declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because __dict__ is not created for each instance.

Emphasis mine.

Which means your class definition must look like:

class Player(object):
    __slots__ = ['name','age','gsnum']
    def __init__(self,name,age,gsnum):
        self.name = name
        self.age = age
        self.gsnum = gsnum

You can tell if you've got it right if you try to assign a variable that does not exist in the slots definition. You'll get an AttributeError.

Incidentally with the new type class definition the class is 32 bytes but with the slots its 36 bytes on my system.

user2357112
  • 260,549
  • 28
  • 431
  • 505
Serdalis
  • 10,296
  • 2
  • 38
  • 58
  • +1 -- Good catch. I didn't realize that the OP is using an outdated python version and forgot to inherit from `object`. BTW: seems like `__slots__` decreases memory only with a single attribute. – Bakuriu May 04 '16 at 04:50
  • why using object? you can test the size when using object, much bigger – Eric Wang May 04 '16 at 04:52
  • @EricWang 'New Style' python class definitions must inherit from `object` unless using python 3, where they're new by default. `__slots__` will only work with new style classes as the docs state. – Serdalis May 04 '16 at 04:55
  • Ok. thanks. but why the opposite result? – Eric Wang May 04 '16 at 04:57
  • @EricWang I may have mis-understood your question then, what is the problem you are having? – Serdalis May 04 '16 at 04:58
  • isn't the slots supposed to transfer the dict(object attributes) to tuple/list?that is for saving memory, but our results aren't obey the rule here. I forgot where, maybe david beazley demonstrated before, it sure save memory for one instance – Eric Wang May 04 '16 at 05:00
  • 1
    @EricWang: `sys.getsizeof` is shallow. It doesn't report the memory occupied by objects that you might think of as "part of" the object if they're separate objects. For example, it doesn't count the size of the `__dict__` or anything the `__dict__` refers to. – user2357112 May 04 '16 at 05:08
  • @user2357112 yeah, I guess that's the problem here, is there other ways exist to check the size? maybe the original c file? – Eric Wang May 04 '16 at 05:10
  • Note that using `sys.getsizeof` isn't the right choice. It will measure the size of the `PyObject` struct for the class. For regular object this does *not* include the `__dict__`. But when using `__slots__` the struct contains the fields so it will seem bigger, but overall memory footprint will be smaller. (@EricWang) – Guy Dec 27 '18 at 09:45