I have the feeling I've seen this somewhere, but am no longer sure whether that's a re-constructed memory or if it really exists. In any case I cannot find a reference to this situation:
class A:
a = 1
class B(A): # should have it's own class attribute 'a'
pass
class C(A): # should have it's own class attribute 'a' and newly defined 'c'
c = 3
In the above example, A.a is B.a is C.a
. But, I actually wanted them to be separate while keeping this structure. There is a good reason for this and I don't want to discuss instance variables. The reason for that is that in my application all these classes are used as 'namespaces'. To solve the 'issue', I replace A
inherited parts by a copy of itself as (pseudo code):
class A:
a = 1
class B(A): # B.a resolves to A.a
pass
class C(A): # C.a resolves to A.a
c = 3
copy_func(B.A, A) # investigates public attrs of A and B and create copies, now B.a is not A.a
copy_func(C.A, A) # investigates public attrs of A and B and create copies, now C.a is not A.a
CodePudding user response:
Define __init_subclass__
to automatically copy superclass-attributes when a childclass is defined.
import copy
class A:
a = []
def __init_subclass__(cls, **kwargs):
for base in cls.mro():
for attr in base.__dict__:
if attr not in cls.__dict__ and not attr.startswith("_"):
setattr(cls, attr, copy.copy(getattr(cls, attr)))
This will copy everything from the superclass namespace that does not start with _
. In practice, one might want to apply more restrictive rules.
The __init_subclass__
is automatically run when a subclass is defined. This means subclasses gain the copied attributes without having to run code explicitly.
class B(A):
pass
class C(A):
c = 3
assert B.a is not A.a
assert C.a is not A.a