title: How to use `__slots__` with initialization of attributes?
body: <p>I read through the main answers on <a href="https://stackoverflow.com/questions/472000/usage-of-slots">usage of slots</a> and it has given me an idea of how and where to use <code>__slots__</code> . </p>
  
  <p>Now, I am porting a code from Python 2 to Python 3 which is similar to as following:</p>
  
  <pre><code>class B(object):
      __slots__ = ('_fields')
      _fields = set()
  </code></pre>
  
  <p>But this is giving error Python 3 while working fine on Python 2:</p>
  
  <p><strong><code>ValueError: '_fields' in __slots__ conflicts with class variable</code>.</strong> </p>
  
  <p>I change the code to </p>
  
  <pre><code>class B(object):
      __slots__ = ('_fields')
      def __init__(self):
          _fields = set()
  </code></pre>
  
  <p>and it works fine. My query is, is it even the correct change ?</p>
  
  <p>As i got from original code, I guess it is saying that don't use <code>__dict__</code> for saving memory or faster access or whatever reason but at the same time is also trying to specify the type of attribute <code>_field</code> as set(). Can the change above be the right way to say it or it can have some side effects.</p>
  
  <hr>
  
  <p><strong>Further Experiments</strong>: 
  I experimented further with following variants (on Python 3): </p>
  
  <pre><code>import pdb
  
  class A(object):
      a = set()
  
  '''
  class B(object):
      __slots__ = ('a')
      a = set()
  '''
  
  class C(object):
      __slots__ = ('a')
      def __init__(self):
          a = set()
  
  class D(object):
      def __init__(self):
          __slots__ = ('a')
          a = set()
  
  if __name__ == '__main__':
      #pdb.set_trace()
      x = A(); print(dir(x))
      #y = B()
      z = C(); print(dir(z))
      z1 = D(); print(dir(z1))
  </code></pre>
  
  <p>and it gave following output. </p>
  
  <pre><code>['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a']
  
  
  ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'a']
  
  
  ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
  </code></pre>
  
  <p>We can see that only C object shows correct footprint i.e. no <code>__dict__</code> and only <code>__slots__</code> . Isn't it what ideally we would want ? Any explanation on <code>__weakref__</code> would also be helpful.</p>
  
  <p>Also on Python 2, both B and C object show same footprint. Based on that should C be the right way to put it as it is compiling on both Python 2 and 3 as well.</p>