If the object does not have `__dict__`, should its class have the attribute` __slots__`?

From overflow.site/questions/89442 / ...

To support arbitrary attribute assignment, an object needs __dict__ : dict associated with the object, where arbitrary attributes can be stored. Otherwise, there is nowhere to add new attributes.

The object instance does not carry around __dict__ - if so, facing the terrible circular dependency problem (since __dict__ , like most everything else, inherits from object ;-), this will saddle every object in Python with a dict, which would mean overhead for many bytes to an object that currently does not have or needs a dict (essentially, all objects that do not have arbitrary attributes do not have or need a dict).

...

If a class has a special __slots__ attribute (a sequence of strings), then the class operator (more precisely, the default metaclass, type ) does not equip each instance of this class with __dict__ (and, therefore, the ability to have arbitrary attributes), just a finite hard set of β€œslots” (mainly places, each of which may contain one link to any object) with the specified names.

If an object does not have __dict__ , should its class have the __slots__ attribute?

For example, an instance of object does not have __dict__ ,

 >>> object().__dict__ Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'object' object has no attribute '__dict__' 

but

 >>> object.__slots__ Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: type object 'object' has no attribute '__slots__' 

So, why does the object instance not have __dict__ and object not have the __slots__ attribute?

Does the object instance have any attribute?

How many possibilities are there:

  • the object has __dict__ , and its class has __dict__ , but not __slots__
  • the object does not have __dict__ , and its class has __slots__
  • the object does not have __dict__ , and its class does not have __slots__ ?

Is it possible to indicate whether an object has __dict__ from its class?

  • if his class has __slots__ , then he does not have __dict__
  • If its class does not have __slots__ , how can I determine if it has __dict__ or not?
+3
python
04 Oct '17 at 22:33
source share
1 answer

For custom classes (defined using the class keyword in regular Python code), the class will always have __slots__ in the class, __dict__ in the instance, or both (if one of the specified slots is '__dict__' , or one of the user-defined classes in the inheritance chain defines __slots__ , and the other is not, creating __dict__ implicitly). So three of the four possibilities cover user-defined classes.

Edit: Correction: technically a custom class cannot have either ; the class will be defined using __slots__ , but delete it after the definition time (the mechanism that sets the type does not require __slots__ to __slots__ saved after the class definition is complete). No sane person should do this, and he may have unwanted side effects (complete behavior unverified), but it is possible.

For built-in types, at least in the CPython reference interpreter, they hardly have __slots__ (if that were the case, then it would be to simulate a custom class that defines it is really nothing useful). The built-in type typically saves its attributes as C-level source values ​​and pointers to a C-level structure, optionally with explicitly created descriptors or access methods, which excludes the purpose of __slots__ , which are just a convenient equivalent equivalent to struct games for custom classes. __dict__ is an option for built-in types, not the default (although the commissioning process is quite simple, you need to put the PyObject* entry somewhere in the structure and provide it with an offset in the type definition).

To be clear, __dict__ must not appear in a class so that it appears in its instances; __slots__ is a class level and can suppress __dict__ in an instance, but does not affect whether the class itself has __dict__ ; custom classes always have __dict__ , but their instances will not be if you use __slots__ .

In short:

(Sane) User-defined classes have at least one of __dict__ (in instances) or __slots__ (in the class) and can have both. Crazy custom classes did not have a single one, but only an abnormal developer could do this.

Built-in classes often do not, can provide __dict__ and almost never provide __slots__ , since it makes no sense to them.

Examples:

 # Class has __slots__, instances don't have __dict__ class DictLess: __slots__ = () # Instances have __dict__, class lacks __slots__ class DictOnly: pass # Class has __slots__, instances have __dict__ because __slots__ declares it class SlottedDict: __slots__ = '__dict__', # Class has __slots__ without __dict__ slot, instances have it anyway from unslotted parent class DictFromParent(DictOnly): __slots__ = () # Complete insanity: __slots__ takes effect at class definition time, but can # be deleted later, without changing the class behavior: class NoSlotNoDict: __slots__ = () del NoSlotNoDict.__slots__ # Instances have no __dict__, class has no __slots__ but acts like it does # (the machinery to make it slotted isn't undone by deleting __slots__) # Please, please don't actually do this # Built-in type without instance __dict__ or class defined __slots__: int().__dict__ # Raises AttributeError int.__slots__ # Also raises AttributeError # Built-in type that opts in to __dict__ on instances: import functools functools.partial(int).__dict__ # Works fine functools.partial.__slots__ # Raises AttributeError 
+6
Oct 04 '17 at 10:49 on
source share



All Articles