title: dataclasses.dataclass with __init_subclass__
body: <p>My confusion is with the interplay between <code>dataclasses</code> &amp; <code>__init_subclass__</code>.</p>
  <p>I am trying to implement a base class that will exclusively be inherited from. In this example, <code>A</code> is the base class. It is my understanding from reading the python docs on <a href="https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass" rel="nofollow noreferrer">dataclasses</a> that simply adding a decorator should automatically create some special dunder methods for me. Quoting their docs:</p>
  <hr />
  <blockquote>
  <p>For example, this code:</p>
  </blockquote>
  <pre><code>from dataclasses import dataclass
  
  @dataclass
  class InventoryItem:
      &quot;&quot;&quot;Class for keeping track of an item in inventory.&quot;&quot;&quot;
      name: str
      unit_price: float
      quantity_on_hand: int = 0
  
      def total_cost(self) -&gt; float:
          return self.unit_price * self.quantity_on_hand
  </code></pre>
  <blockquote>
  <p>will add, among other things, a <code>__init__()</code> that looks like:</p>
  </blockquote>
  <pre><code>def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0):
      self.name = name
      self.unit_price = unit_price
      self.quantity_on_hand = quantity_on_hand
  </code></pre>
  <hr />
  <p>This is an instance variable, no? From the classes <a href="https://docs.python.org/3/tutorial/classes.html" rel="nofollow noreferrer">docs</a>, it shows a toy example, which reads super clear.</p>
  <pre><code>class Dog:
  
      kind = 'canine'         # class variable shared by all instances
  
      def __init__(self, name):
          self.name = name    # instance variable unique to each instance
  </code></pre>
  <p>A main gap in my understanding is - is it an instance variable or a class variable? From my testing below, it is a class variable, but from the docs, it shows an instance variable as it's proximal implementation. It may be that most of my problem is there. I've also read the python docs on <a href="https://docs.python.org/3/tutorial/classes.html" rel="nofollow noreferrer">classes</a>, which do not go into <code>dataclasses</code>.</p>
  <hr />
  <p>The problem continues with the seemingly limited docs on <a href="https://docs.python.org/3/reference/datamodel.html?highlight=__init_subclass__#customizing-class-creation" rel="nofollow noreferrer"><code>__init_subclass__</code></a>, which yields another gap in my understanding. I am also making use of <code>__init_subclass__</code>, in order to enforce that my subclasses have indeed instantiated the variable <code>x</code>.</p>
  <p>Below, we have <code>A</code>, which has an instance variable <code>x</code> set to None. <code>B</code>, <code>C</code>, and <code>D</code> all subclass <code>A</code>, in different ways (hoping) to determine implementation specifics.</p>
  <p><code>B</code> inherits from <code>A</code>, setting a class variable of <code>x</code>.
  <code>D</code> is a dataclass, which inherits from <code>A</code>, setting what would appear to be a class variable of <code>x</code>. However, given their docs from above, it seems that the class variable <code>x</code> of <code>D</code> should be created as an instance variable. Thus, when <code>D</code> is created, it should first call <code>__init_subclass__</code>, in that function, it will check to see if <code>x</code> exists in <code>D</code> - by my understanding, it <em>should</em> not; however, the code passes scot-free. I believe <code>D()</code> will create <code>x</code> as an instance variable because the dataclass <a href="https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass" rel="nofollow noreferrer">docs</a> show that this will create an <code>__init__</code> for the user.</p>
  <blockquote>
  <p>&quot;will add, among other things...&quot; &lt;insert <code>__init__ code</code>&gt;</p>
  </blockquote>
  <p>I must be wrong here but I'm struggling to put it together.</p>
  <pre><code>import dataclasses
  
  class A:
      def __init__(self):
          self.x = None
  
      def __init_subclass__(cls):
          if not getattr(cls, 'x') or not cls.x:
              raise TypeError(
                  f'Cannot instantiate {cls.__name__}, as all subclasses of {cls.__base__.__name__} must set x.'
              )
  
  
  class B(A):
      x = 'instantiated-in-b'
  
  
  @dataclasses.dataclass
  class D(A):
      x : str = 'instantiated-in-d'
  
  
  
  class C(A):
      def __init__(self):
          self.x = 'instantiated-in-c'
  
  
  print('B', B())
  print('D', D())
  print('C', C())
  </code></pre>
  <p>The code, per my expectation, properly fails with <code>C()</code>. Executing the above code will succeed with <code>D</code>, which does not compute for me. In my understanding (which is wrong), I am defining a <code>field</code>, which means that <code>dataclass</code> should expand my class variables as instance variables. (The previous statement is most probably where I am wrong, but I cannot find anything that documents this behavior. Are data classes not actually expanding class variables as instance variables? It certainly appears that way from the visual explanation in their docs.) From the dataclass <a href="https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass" rel="nofollow noreferrer">docs</a>:</p>
  <blockquote>
  <p>The dataclass() decorator examines the class to find fields. A field is defined as a class variable that has a type annotation.</p>
  </blockquote>
  <hr />
  <p>Thus - <strong>why</strong> - when creating an instance <code>D()</code> - does it slide past the <code>__init_subclass__</code> of its parent <code>A</code>?</p>
  <p>Apologies for the lengthy post, I must be missing something simple, so if once can point me in the right direction, that would be excellent. TIA!</p>
  <hr />
  <p>I have just found the <a href="https://github.com/python/cpython/blob/main/Lib/dataclasses.py" rel="nofollow noreferrer">implementation for dataclasses</a> from the CPython github.</p>
  <p>Related Articles:</p>
  <ul>
  <li><a href="https://stackoverflow.com/questions/45400284/understanding-init-subclass">Understanding __init_subclass__</a></li>
  <li><a href="https://stackoverflow.com/questions/475871/python-why-use-self-in-a-class">python-why-use-self-in-a-class</a></li>
  <li><a href="https://stackoverflow.com/questions/109087/how-to-get-instance-variables-in-python">proper-way-to-create-class-variable-in-data-class</a></li>
  <li><a href="https://stackoverflow.com/questions/61937520/proper-way-to-create-class-variable-in-data-class">how-to-get-instance-variables-in-python</a></li>
  <li><a href="https://stackoverflow.com/questions/22046369/enforcing-class-variables-in-a-subclass">enforcing-class-variables-in-a-subclass</a></li>
  </ul>