Python 什么是元类?
在Python中,元编程被定义为程序影响本身的能力。这是通过使用Python中的元类来实现的。
阅读更多:Python 教程
Python中的元类
元类是所有Python代码中默认存在的OOP概念。Python通过使用关键字 type 来提供创建自定义元类的功能。type是一个元类,其实例是类。Python中创建的任何类都是type元类的一个实例。
type() 函数可以动态地创建类,因为调用type()会创建type元类的新实例。
句法
使用type()创建类的句法如下所示 –
class name = type(name>, bases>, dct>
其中:
<name> 是类名。
<bases> 定义一个元素为类的元组,从中类将继承。
<dct> 定义了一个命名空间字典,其中包含类的定义。
示例1
这是最简单的类定义,因为参数 bases 和 dct 都是空的,因此没有继承和命名空间字典。
DemoClass = type('DemoClass', (), {})
obj = DemoClass()
print(obj)
输出
以上代码的输出会生成一个变量DemoClass,该变量包含对类的引用。
<__main__.DemoClass object at 0x7fde96524240>
示例2
在下面的示例中,第二个参数 bases 是一个由元组组成的元组,其中有一个名为Demo的元素,从中类Demo2继承。
class Demo:
pass
Demo2 = type('Demo2', (Demo,), dict(attribute=10))
obj = Demo2()
print(obj.attribute)
print(obj.__class__)
print(obj.__class__.__bases__)
输出
在以上程序的输出中,打印属性将给出10,因为它被存储在 dct 参数中。打印类将输出Demo2,因为它是派生类,而打印基类将给出Demo,因为它在 bases 参数中存在。
10
class '__main__.Demo2'>
(class '__main__.Demo'>,)
示例3
在下面的示例中, dct 参数具有attribute和attribute_value两个参数,它们充当Demo类的方法。
Demo = type('Demo', (), {
'attribute': 10,
'attribute_value': lambda obj: obj.attribute
})
obj = Demo()
print(obj.attribute)
print(obj.attribute_value())
输出
以上程序在
10
10
示例4
以下示例中在
def s(obj):
print('Attribute value =', obj.attribute)
Demo = type('Demo',(),
{
'attribute': 10,
'attribute_value': s
}
)
object = Demo()
print(object.attribute)
object.attribute_value()
输出
输出结果中,attribute 和 attribute_value 两个实例的输出值均为10,因为 attribute 变量的值为10,当调用 attribute_value 时会获取到外部分配的函数 s。程序然后执行函数 s,运行 attribute_value 的 print 语句。
10
Attribute value = 10
Python 中的自定义元类
Python 允许通过在创建新类时将 type 作为参数来创建自定义元类。元类也称为类工厂,因为它们可以用作创建类的模板。
创建自定义元类的示例
在此示例中,MetaClass 是一个自定义元类,因为它继承自 type,而 type 本身就是一个元类。这允许创建 new(),它执行以下操作−
- 调用父元类 type 通过 super() 来创建新类
- 为该类创建自定义属性
- 返回创建的类
MetaClass 然后可以作为 CustomClass 的创建模板,因此 CustomClass 继承了 MetaClass 的属性。
示例
下面是创建自定义元类的示例−
class MetaClass(type):
def __new__(self,name,base,dct):
obj = super().__new__(self,name,base,dct)
obj.attribute = 10
return obj
# MetaClass 作为 CustomClass 的模板
class CustomClass(metaclass = MetaClass):
pass
print<(CustomClass.attribute)
输出
以下是以上代码的输出结果:
10