Python 元类MetaClass是什么
在python中,元编程被定义为程序影响自己的能力。通过使用元类,可以实现元编程。
Python中的元类
元类是面向对象编程概念,默认在所有Python代码中存在。Python提供了使用关键字 type 创建自定义元类的功能。Type是一个元类,其实例是类。在Python中创建的任何类都是type元类的实例。
type() 函数可以动态地创建类,调用type()会创建一个type元类的新实例。
语法
使用type()创建类的语法如下:
class name = type(name>, bases>, dct>
在下面
<name>
是类名
<bases>
定义了一个元组,其中包含类将继承的基类
<dct>
定义了一个命名空间字典,其中包含类的定义
示例1
这是最简单的类定义,因为 和 参数都为空,因此没有继承和命名空间字典为空。
DemoClass = type('DemoClass', (), {})
obj = DemoClass()
print(obj)
输出
上述代码的输出会得到一个名为 DemoClass 的变量,它持有对类的引用。
<__main__.DemoClass object at 0x7fde96524240>
示例2
在下面的示例中,第二个参数**是一个元组,其中只有一个元素 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,因为它已经存储在参数中。打印类会得到Demo2作为输出,因为它是派生类,并且打印基类会得到Demo作为结果,因为它存在于参数中。
10
class '__main__.Demo2'>
(class '__main__.Demo'>,)
示例3
以下是一个示例,<dct>
参数有一个属性变量和属性值,它作为Demo类的方法。
Demo = type('Demo',(),
{
'attribute': 10,
'attribute_value': lambda obj : obj.attribute
}
)
obj = Demo()
print(obj.attribute)
print(obj.attribute_value())
输出
上述程序对两个实例都给出了数值10,因为attribute已经被赋值为10, 并且attribute_value是一个调用attribute变量的方法,而该变量的赋值为10。
10
10
示例4
在下面的示例中,一个外部创建的函数被赋值给了<dct>
中的attribute_value参数,以替代lambda函数,因为lambda函数只能执行简单的任务。
def s(obj):
print('Attribute value =', obj.attribute)
Demo = type('Demo',(),
{
'attribute': 10,
'attribute_value': s
}
)
object = Demo()
print(object.attribute)
object.attribute_value()
输出
输出结果再次为属性和属性值都是10。由于属性变量的值是10,当调用属性值时,它会调用外部分配的函数s。然后程序执行函数s,运行属性值的打印语句。
10
Attribute value = 10
在Python中创建自定义的元类
在创建新类时,Python允许通过将type作为参数传递来创建自定义的元类。元类也被称为类工厂,因为它们可以用作创建类的模板。
创建自定义元类的示例
在这个示例中,MetaClass是一个自定义的元类,因为它继承自type,而type本身就是一个元类。这允许创建new()方法,该方法执行以下操作:
- 通过super()调用父元类type来创建新类
- 为类创建自定义属性
- 返回创建的类
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 acts as template for CustomClass
class CustomClass(metaclass = MetaClass):
pass
print(CustomClass.attribute)
输出
以下是上述代码的输出结果-
10