How do I properly inherit data from an instantiation of a super class? For example, consider something I can get to work, but is confusing in its behaviour:
from dataclasses import dataclass
from typing import Self
@dataclass
class SuperClass:
hello: int
world: int
@dataclass
class ChildClass(SuperClass):
kitty: int
@classmethod
def from_super(cls, s: SuperClass, kitty: int) -> Self:
x = cls(s, kitty=kitty)
return x
Now, let’s see whether this works:
super_instance = SuperClass(0, 1)
child = ChildClass.from_super(super_instance, 2)
child
This produces output:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[48], line 1
----> 1 ChildClass.from_super(super_instance, 2)
Cell In[46], line 15
13 @classmethod
14 def from_super(cls, s: SuperClass, kitty: int) -> Self:
---> 15 x = cls(s, kitty=kitty)
16 return x
TypeError: ChildClass.__init__() missing 1 required positional argument: 'world'
So how do I do this correctly, without manually writing out each variable instantiation from the super class?
In your example, you seem to be trying to inherit data from an instance of a superclass (SuperClass
) to a subclass (ChildClass
). However, your approach has some issues, primarily due to the way the dataclass
decorator and inheritance work in Python.
To properly inherit data from an instantiation of a superclass, you need to use inheritance. Let’s modify your code to demonstrate the proper way to do this using inheritance:
- Make
ChildClass
inherit fromSuperClass
. - Use the
super()
function to initialize the superclass part.
from dataclasses import dataclass
from typing import Self
@dataclass
class SuperClass:
hello: int
world: int
@dataclass
class ChildClass(SuperClass):
kitty: int
@classmethod
def from_super_wtf(cls, s: SuperClass, kitty: int) -> Self:
x = cls(hello=s.hello, world=s.world, kitty=kitty)
return x
@classmethod
def from_super_works(cls, s: SuperClass, kitty: int) -> Self:
x = cls(hello=s.hello, world=s.world, kitty=kitty)
return x
@classmethod
def from_super_sane(cls, s: SuperClass, kitty: int) -> Self:
x = cls(hello=s.hello, world=s.world, kitty=kitty)
return x
# Testing the code
super_instance = SuperClass(0, 1)
child = ChildClass.from_super_works(super_instance, 2)
child_wtf = ChildClass.from_super_wtf(super_instance, 2)
child_sane = ChildClass.from_super_sane(super_instance, 2)
print(child) # Expected: ChildClass(hello=0, world=1, kitty=2)
print(child_wtf) # Expected: ChildClass(hello=0, world=1, kitty=2)
print(child_sane) # Expected: ChildClass(hello=0, world=1, kitty=2)
In this approach, ChildClass
inherits from SuperClass
, which means it also inherits the hello
and world
attributes. When creating a new instance
1