如何编写自己的元类?

How to write own metaclass?

如何在python中创建元类?我试着像教程中那样写:

class Meta(type):

    def __new__(mcs, name, bases, attrs):
        attrs2 = {'field2': 'Test'}
        attrs2.update(attrs)
        return super(Meta, mcs).__new__(mcs, name, bases, attrs2)


class Test(object):
    __metaclass__ = Meta

    field1 = 10


test = Test()

print(test.field1)
print(test.field2)

但是此代码失败并出现错误:

10                                                                                                                                                                                 
Traceback (most recent call last):                                                                                                                                                 
  File "main.py", line 18, in <module>                                                                                                                                             
    print(test.field2)                                                                                                                                                             
AttributeError: 'Test' object has no attribute 'field2'  

如何在 python 3.7+ 中正确声明元类?

已更新 我已经用实际错误更改了我的问题。

您查看的教程涵盖Python 2.

在 Python 3 中,语法更改之一就是为 class 声明元 class 的方式。 您无需更改 metaclass 代码,只需将 class 声明更改为:


class Test(metaclass=Meta):

    field1 = 10

它会起作用。

所以,简而言之:对于 Python 3 中的元 class,您必须在 class 声明中传递相当于 "keyword argument" 的内容,其中姓名 "metaclass"。 (另外,在Python 3中,不需要显式继承自object)

在 Python 2 中,这是通过在 class 的 body 中存在特殊变量 __metaclass__ 来实现的,如您的示例所示。 (此外,当设置元 class 时,从 'object' 继承是可选的,因为从类型派生的元 class 会为你做这件事。

新语法的主要优点之一是它允许元class中的特殊方法__prepare__可以return自定义命名空间object在构建 class body 本身时使用。它很少使用,今天很难提出一个真正的 "serious" 用例。对于玩具和玩耍来说,这很棒,允许 "magic autonamed enumerations" 和其他东西 - 但在设计 Python 3 时,他们认为这是允许 OrderedDict 作为 class 命名空间,以便 metaclass' __new____init__ 方法可以知道属性声明的顺序。从 Python 3.6 开始,class body 命名空间默认排序,不需要单独使用 __prepare__ 方法。