How do I add self.value 1 and self.value 2 into VALUES . this is the purpose How can I add "self.value1" and "self.value2" to the VALUES list inside the meta class
class Meta(type):
VALUES = dict()
def __new__(mcs, name, bases, attrs):
for k, v in attrs.items():
print(k, v)
return super(Meta, mcs).__new__(mcs, name, bases, attrs)
class A(metaclass=Meta):
def __init__(self):
self.value1 = "Class A"
class B(metaclass=Meta):
def __init__(self):
self.value2 = "Class B"
class Main(A, B):
def __init__(self):
super(Main, self).__init__()
m = Main()
print(m.__dict__)
the output i wanted {'value1': 'Class A',"value2":"Class B"}
CodePudding user response:
This is because when you call the super() function, it doesn't call all instances of the function, only the first one it finds. Because your class definition inherits A before it inherits B, the first class to be searched is class A. The program finds the init function inside class A so it executed that and then returns. If you were instead to write class Main(B, A):
, the output would be {"value2":"Class B"}
, because then class B is higher in the search order than A.
To solve the problem you have, you would have to run all of the inherited class's init functions, for example like this:
class Main(A, B):
def __init__(self):
for cls in Main.__bases__:
cls.__init__(self)
This takes a reference from each parent class from the bases attribute and calls their init directly, meaning that it is called from every parent class, not just the highest priority one. I'm not sure if this is best practice or even sensible at all but it should the problem you described.
CodePudding user response:
super
is meant to be used cooperatively, by all classes in the hierarchy. (Ignoring the metaclass, since it is irrelevant to the requested result.)
class A:
def __init__(self. **kwargs):
super().__init__(**kwargs)
self.value1 = "Class A"
class B:
def __init__(self. **kwargs):
super().__init__(**kwargs)
self.value2 = "Class B"
class Main(A, B):
pass
m = Main()
Since Main.__init__
isn't defined, the first __init__
method found in the MRO is called first, namely A.__init__
. A.__init__
then uses super()
to call B.__init__
, which uses super()
to call object.__init__
, which is the last method in the chain, as object.__init__
itself does not use super
.
Note that both A
and B
use super
without knowing which class's __init__
method will be used next. That is determined by the type of the object passed as self
, not the class.