How to use `__slots__` with initialization of attributes?
But this is giving error Python 3 while working fine on Python 2:
ValueError: '_fields' in __slots__ conflicts with class variable
.
While you didn't get an error in Python2 at class creation/compile time like in Py3k, if you try to actually set the value of _fields
, you get AttributeError: 'C' object attribute '_fields' is read-only
:
>>> class C(object):
... __slots__ = ('_fields')
... _fields = set()
...
>>>
>>> c = C()
>>> c._fields
set([])
>>> c._fields = 'foo'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object attribute '_fields' is read-only
>>>
Also, see the fourth note in the slots documentation:
__slots__
are implemented at the class level by creating descriptors (Implementing Descriptors) for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by__slots__
; otherwise, the class attribute would overwrite the descriptor assignment.
Wrt your modification:
I change the code to
class B(object): __slots__ = ('_fields') def __init__(self): _fields = set()
The modified class B has a _fields
inside __init__()
, not self._fields
so it's just a local variable in init, and not accessible anywhere else in the class. Change that to:
class B(object):
__slots__ = ('_fields')
def __init__(self):
self._fields = set()
To correctly initialise _fields
, do this:
class B(object):
__slots__ = ('_fields')
def __init__(self, _fields=None):
if not _fields:
self._fields = set()
Wrt further experimentation:
In class D, __slots__
is a variable only inside __init()__
. It's not the (special) class variable D.__slots__
; or even the instance variable self.__slots__
. So it has __dict__
.
Class A has none, so also has __dict__
.
Class C has __slots__
correctly.