0

我有一个数据类 A 可以被继承并用于创建其他类。每次继承我的 A 类时,我都想将子类注册到容器中。我想用元类解决它,但它对我不起作用。请问有什么帮助吗?

container = {}

class Meta(type):
    def __new__(mcs, *args, **kwargs):
        new_class = super().__new__(mcs, *args, **kwargs)

        if new_class.__name__ != 'A':
            container[new_class.__name__] = new_class

        return new_class


@metaclass
class MasterClass:
    parent


@metaclass
class A(MasterClass, metaclass=Meta):
    my_arg


@metaclass
class Child(A): # <-- this class I would like to register into child container
    my_next_arg

4

1 回答 1

1

您的代码几乎是正确的,但是当它应该是“@dataclass”装饰器时使用“@metaclass”,并在字段上创建一些注释,否则您将遇到 NameError 异常。

所以,如果你这样做:

from dataclasses import dataclass
from typing import Any
container = {}

class Meta(type):
    def __new__(mcs, *args, **kwargs):
        new_class = super().__new__(mcs, *args, **kwargs)

        if new_class.__name__ != 'A':
            container[new_class.__name__] = new_class

        return new_class


@dataclass
class MasterClass:
    parent: Any


@dataclass
class A(MasterClass, metaclass=Meta):
    my_arg: Any


@dataclass
class Child(A): # <-- this class I would like to register into child container
    my_next_arg: Any

它将按您的预期工作,并将Child在容器中注册:

In [5]: container                                                                                                                    
Out[5]: {'Child': __main__.Child}

请注意,从 Python 3.6 开始,您不需要为此模式使用元类,因为在__init_subclass__创建子类时会调用 classmethod,并且可以执行相同的操作:


from dataclasses import dataclass
from typing import Any

container = {}

@dataclass
class MasterClass:
    parent: Any


@dataclass
class A(MasterClass):
    def __init_subclass__(cls, *args, **kw):
        super().__init_subclass__(*args, **kw)
        container[cls.__name__] = cls

    my_arg: Any


@dataclass
class Child(A): # <-- this class I would like to register into child container
    my_next_arg: Any
于 2020-05-20T04:13:39.827 回答