摘要:通过替换新类默认使用的 type 元类,元类允许您深入修改 Python 类的行为(在如何定义、实例化、访问等方面)。
通过替换新类默认使用的 type 元类,元类允许您深入修改 Python 类的行为(在如何定义、实例化、访问等方面)。
当调用带有三个参数的 type 时,它的行为就像(Meta)类一样,并创建一个新的实例,即产生一个新的类/类型。
Dummy = type('OtherDummy', , dict(x=1))Dummy.__class__ # Dummy.__class__.__class__ #可以对类型进行子类化,创建自定义元类。
class mytype(type):def __init__(cls, name, bases, dict):# 调用基础初始化器type.__init__(cls, name, bases, dict)# 执行自定义初始化...cls.__custom_attribute__ = 2现在,我们有了一个新的自定义 mytype 元类,可以用与 type 相同的方式创建类。
MyDummy = mytype('MyDummy', , dict(x=2))MyDummy.__class__ # MyDummy.__class__.__class__ # MyDummy.__custom_attribute__ # 2当我们使用 class 关键字创建一个新类时,默认情况下会根据基类选择元类。
>>> class Foo(object):... pass>>> type(Foo)type在上面的例子中,唯一的基类是 object,所以我们的元类将是 object 的类型,即 type。我们可以覆盖默认值,但这取决于我们使用的是 Python 2 还是 Python 3:
可以使用特殊的类级属性 __metaclass__ 来指定元类。
class MyDummy(object):__metaclass__ = mytypetype(MyDummy) #一个特殊的元类关键字参数指定了元类。
class MyDummy(metaclass=mytype):passtype(MyDummy) #类声明中的任何关键字参数(“元类 ”除外)都将传递给元类。因此 class MyDummy(metaclass=mytype, x=2) 将把 x=2 作为关键字参数传递给 mytype 构造函数。
请阅读 python 元类的深入介绍「链接」,了解更多详情。
单例是一种将类的实例化限制为一个实例/对象的模式。有关 python 单例设计模式的更多信息,请参见此处 The Singleton Python 3 Patterns, Recipes and Idioms。
class SingletonType(type):def __call__(cls, *args, **kwargs):try:return cls.__instanceexcept AttributeError:cls.__instance = super(SingletonType, cls).__call__(*args, **kwargs)return cls.__instancePython 3.x Version ≥ 3.0
class MySingleton(metaclass=SingletonType):passMySingleton is MySingleton # True, only one instantiation occurs3: 使用元类元类语法
class MyClass(metaclass=SomeMetaclass):passPython 2 和 Python 3 与 six 的兼容性
import sixclass MyClass(six.with_metaclass(SomeMetaclass)):pass4: 元类简介什么是元类? 在 Python 中,一切都是对象:整数、字符串、列表,甚至函数和类本身都是对象。每个对象都是一个类的实例。
要检查对象 x 的类,可以调用 type(x),所以
>>> type(5)>>> type(str)>>> type([1, 2, 3])>>> class C(object):... pass...>>> type(C)python 中的大多数类都是 type 的实例。type 本身也是一个类。这种实例也是类的类称为元类。
最简单的元类
好了,Python 中已经有了一个元类:type。我们能再创建一个吗?
class SimplestMetaclass(type):passclass MyClass(object):__metaclass__ = SimplestMetaclass这并没有增加任何功能,但它是一个新的元类,请看 MyClass 现在是 SimplestMetaclass 的实例:
>>> type(MyClass)做某事的元类
执行某些操作的元类通常会覆盖 type 的 __new__,在调用创建类的原始 __new__ 之前修改要创建类的某些属性:
class AnotherMetaclass(type):def __new__(cls, name, parents, dct):# cls 是这个类# name 是要创建的类的名称# parents 是类的父类列表# dct 是类的属性(方法、静态变量)列表# 这里的所有属性都可以在创建类之前修改,例如dct['x'] = 8 # 现在,该类将有一个静态变量 x = 8# 返回值就是新的类。return super(AnotherMetaclass, cls).__new__(cls, name, parents, dct)元类中的功能可以更改,这样每当类被构建时,就会在标准输出中打印一个字符串,或者抛出一个异常。该元类将打印正在构建的类的名称。
class VerboseMetaclass(type):def __new__(cls, class_name, class_parents, class_dict):print("Creating class ", class_name)new_class = super.__new__(cls, class_name, class_parents, class_dict)return new_class您可以像这样使用元类:
class Spam(metaclass=VerboseMetaclass):def eggs(self):print("[insert example string here]")s = Spams.eggs标准输出将是
Creating class Spam[insert example string here]6: 默认元类您可能听说过 Python 中的一切都是对象。没错,所有对象都有一个类:
>>> type(1)字面 1 是 int 的一个实例。让我们声明一个类:
>>> class Foo(object):... pass...现在让我们将其实例化:
>>> bar = Foobar类是什么类型?
>>> type(bar)很好,bar 是 Foo 的一个实例。但 Foo 本身是什么类呢?
>>> type(Foo)好吧,Foo 本身就是 type 的一个实例。那么类型本身呢?
>>> type(type)那么什么是元类?现在,让我们把它当作一个类的别名。启示
在 Python 中,万物皆对象,因此万物皆有类类的类称为元类默认的元类是 type,到目前为止它是最常用的元类但为什么要了解元类?Python本身是非常 “可黑客化 ”的,如果你要进行元编程等高级操作,或者要控制类的初始化方式,元类的概念就非常重要。
来源:山岚