python散装笔记——39:Metaclasses(元类)

360影视 2025-01-09 01:41 3

摘要:通过替换新类默认使用的 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.__instance

Python 3.x Version ≥ 3.0

class MySingleton(metaclass=SingletonType):passMySingleton is MySingleton # True, only one instantiation occurs3: 使用元类

元类语法

class MyClass(metaclass=SomeMetaclass):pass

Python 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 = Foo

bar类是什么类型?

>>> type(bar)

很好,bar 是 Foo 的一个实例。但 Foo 本身是什么类呢?

>>> type(Foo)

好吧,Foo 本身就是 type 的一个实例。那么类型本身呢?

>>> type(type)

那么什么是元类?现在,让我们把它当作一个类的别名。启示

在 Python 中,万物皆对象,因此万物皆有类类的类称为元类默认的元类是 type,到目前为止它是最常用的元类

但为什么要了解元类?Python本身是非常 “可黑客化 ”的,如果你要进行元编程等高级操作,或者要控制类的初始化方式,元类的概念就非常重要。

来源:山岚

相关推荐