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.