Glossary¶
- dict classes
A regular class whose attributes are stored in the
__dict__
attribute of every single instance. This is quite wasteful especially for objects with very few data attributes and the space consumption can become significant when creating large numbers of instances.This is the type of class you get by default both with and without
attrs
.- slotted classes
A class whose instances have no
__dict__
attribute and define their attributes in a__slots__
attribute instead. Inattrs
, they are created by passingslots=True
to@attr.s
(and are on by default inattr.define
/attr.mutable
/attr.frozen
.Their main advantage is that they use less memory on CPython 1.
However they also come with several possibly surprising gotchas:
Slotted classes don’t allow for any other attribute to be set except for those defined in one of the class’ hierarchies
__slots__
:>>> import attr >>> @attr.s(slots=True) ... class Coordinates(object): ... x = attr.ib() ... y = attr.ib() ... >>> c = Coordinates(x=1, y=2) >>> c.z = 3 Traceback (most recent call last): ... AttributeError: 'Coordinates' object has no attribute 'z'
Slotted classes can inherit from other classes just like non-slotted classes, but some of the benefits of slotted classes are lost if you do that. If you must inherit from other classes, try to inherit only from other slotted classes.
However, it’s not possible to inherit from more than one class that has attributes in
__slots__
(you will get anTypeError: multiple bases have instance lay-out conflict
).Slotted classes must implement
__getstate__
and__setstate__
to be serializable withpickle
protocol 0 and 1. Therefore,attrs
creates these methods automatically forslots=True
classes (Python 2 uses protocol 0 by default).Note
If the
@attr.s(slots=True)
decorated class already implements the__getstate__
and__setstate__
methods, they will be overwritten byattrs
autogenerated implementation by default.This can be avoided by setting
@attr.s(getstate_setstate=False)
or by setting@attr.s(auto_detect=True)
.Also, think twice before using
pickle
.Slotted classes are weak-referenceable by default. This can be disabled in CPython by passing
weakref_slot=False
to@attr.s
2.Since it’s currently impossible to make a class slotted after it’s been created,
attrs
has to replace your class with a new one. While it tries to do that as graciously as possible, certain metaclass features like__init_subclass__
do not work with slotted classes.