简体   繁体   English

如何使用元 class 将“__init__”中的值添加到 VALUES 列表中

[英]how to add values in "__init__" to the list of VALUES with the meta class

How do I add self.value 1 and self.value 2 into VALUES.如何将 self.value 1 和 self.value 2 添加到 VALUES 中。 this is the purpose How can I add "self.value1" and "self.value2" to the VALUES list inside the meta class这就是目的如何将“self.value1”和“self.value2”添加到元 class 内的 VALUES 列表中

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"}我想要的 output {'value1': 'Class A',"value2":"Class B"}

This is because when you call the super() function, it doesn't call all instances of the function, only the first one it finds.这是因为当您调用 super() function 时,它不会调用 function 的所有实例,只会调用它找到的第一个实例。 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. 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.如果您改为编写class Main(B, A): ,则 output 将是{"value2":"Class B"} ,因为在搜索顺序中 class B 高于 A。

To solve the problem you have, you would have to run all of the inherited class's init functions, for example like this:要解决您遇到的问题,您必须运行所有继承类的init函数,例如:

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.这从bases属性中获取每个父 class 的引用并直接调用它们的init ,这意味着它是从每个父 class 调用的,而不仅仅是最高优先级的。 I'm not sure if this is best practice or even sensible at all but it should the problem you described.我不确定这是否是最佳实践,甚至是否明智,但它应该是您描述的问题。

super is meant to be used cooperatively , by all classes in the hierarchy. super意味着被层次结构中的所有合作使用。 (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__ .由于未定义Main.__init__ ,因此首先调用 MRO 中的第一个__init__方法,即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 . A.__init__然后使用super()调用B.__init__ ,后者使用super()调用object.__init__ ,这是链中的最后一个方法,因为object.__init__本身不使用super

Note that both A and B use super without knowing which class's __init__ method will be used next.请注意, AB都使用super而不知道接下来将使用哪个类的__init__方法。 That is determined by the type of the object passed as self , not the class.这取决于作为self传递的 object 的类型,而不是 class。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM