你好,我最近正在寻找Python中的metaclass
。
我了解到我们可以通过这种方式将元类附加到类:
class Metaclass(type):
...
class MyClass(metaclass=Metaclass):
...
- 第一个问题
我想知道上面示例中关键字参数(metaclass=...
)的原则是什么。文档中似乎没有对此进行描述
我知道函数有关键字参数,但我从未见过这种形式发生在类继承中。
- 第二个问题
我们知道我们可以通过这种方式使用type()
函数创建一个类
cls = type(class_name, (base_class,), {func_name: func_ref})
考虑到metaclass=...
形式,在使用type()
而不是class
关键字创建类时如何传递元类?
谢谢叠花!
一般来说,与class
语句一起使用的关键字参数被传递给__init_subclass__
,以该函数认为合适的方式使用。 然而,代码生成器本身使用metaclass
来确定调用什么以定义类。
元类不是传递给type
调用的参数;而是被调用的可调用对象而不是type
。粗略地说,
class MyClass(metaclass=Metaclass):
...
变成了
MyClass = Metaclass('MyClass', (), ...)
type
只是默认元类。
(有关如何执行class
语句的血腥细节可以在语言文档的第 3.3.3 节中找到。
请注意,元类不一定是type
的子类。你可以用元类做真正可怕的事情,比如
>>> class A(metaclass=lambda x, y, z: 3): pass
...
>>> type(A)
<class 'int'>
>>> A
3
元类返回什么并不重要,只要它接受 3 个参数即可。
不过,请不要像这样编写实际代码。class
语句应该生成至少类似于类型的东西。
从某种意义上说,class
语句不如其他语句那么神奇。 例如,def
语句不能自定义以生成除function
实例以外的其他内容,并且通过显式调用types.FunctionType
来创建function
对象要困难得多。
是的,我已经看过这个了,但它没有提供关于类继承中关键字参数的原则,我仍然很困惑
metaclass=...
与继承无关。
Python 中的所有内容都是一个对象。因此,当你定义类MyClass
时,不仅MyClass()
是一个对象,而且类MyClass
本身也是一个对象。
MyClass()
是MyClass
的一个实例,足够简单。
但是,如果MyClass
也是一个对象,那么它是哪个类的实例?
如果您什么都不做,则对象 (!MyClass
是类type
的一个实例。
如果您这样做class MyClass(metaclass=Metaclass)
那么MyClass
是Metaclass
的实例。
考虑
class Metaclass(type):
pass
class MyClass1:
pass
class MyClass2(metaclass=Metaclass):
pass
MyClass1
和MyClass2
都继承自object
,而且只有object
。
>>> MyClass1.__mro__
(<class '__main__.MyClass1'>, <class 'object'>)
>>> MyClass2.__mro__
(<class '__main__.MyClass2'>, <class 'object'>)
但它们的类型不同:
>>> type(MyClass1)
<class 'type'>
>>> type(MyClass2)
<class '__main__.Metaclass'>
你什么时候需要这个?通常,你不会。当你这样做时,你会做那种元编程,你已经知道为什么和如何。