gpt4 book ai didi

Python 元类 : Understanding the 'with_metaclass()'

转载 作者:IT老高 更新时间:2023-10-28 20:36:17 25 4
gpt4 key购买 nike

我想问一下with_metaclass()调用在类的定义中是什么意思。

例如:

class Foo(with_metaclass(Cls1, Cls2)):
  • 类从元类继承是一种特殊情况吗?
  • 新类也是元类吗?

最佳答案

with_metaclass() six library 提供的实用类工厂函数,可以更轻松地为 Python 2 和 3 开发代码。

它对临时元类使用了一些技巧(见下文),以与 Python 2 和 Python 3 交叉兼容的方式将元类附加到常规类。

引用文档:

Create a new class with base class base and metaclass metaclass. This is designed to be used in class declarations like this:

from six import with_metaclass

class Meta(type):
pass

class Base(object):
pass

class MyClass(with_metaclass(Meta, Base)):
pass

这是必需的,因为附加元类的语法在 Python 2 和 3 之间发生了变化:

Python 2:

class MyClass(object):
__metaclass__ = Meta

Python 3:

class MyClass(metaclass=Meta):
pass

with_metaclass() 函数利用了元类 a) 由子类继承的事实,b) 元类可用于生成新类,以及 c) 当您从具有元类的基类子类化时,创建实际的子类对象被委托(delegate)给元类。它有效地创建了一个具有临时 metaclass 元类的新临时基类,当用于创建子类时交换临时基类和元类与您选择的元类组合:

def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
# This requires a bit of explanation: the basic idea is to make a dummy
# metaclass for one level of class instantiation that replaces itself with
# the actual metaclass.
class metaclass(type):

def __new__(cls, name, this_bases, d):
return meta(name, bases, d)

@classmethod
def __prepare__(cls, name, this_bases):
return meta.__prepare__(name, bases)
return type.__new__(metaclass, 'temporary_class', (), {})

分解以上内容:

  • type.__new__(metaclass, 'temporary_class', (), {}) 使用 metaclass 元类创建一个名为 temporary_class 的新类对象,否则该对象完全为空。使用 type.__new__(metaclass, ...) 代替 metaclass(...) 是为了避免使用特殊的 metaclass.__new__() 实现,这是在下一步工作中的轻微操作所需的。
  • 仅在 Python 3 中,当 temporary_class 用作基类时,Python 首先调用 metaclass.__prepare__()(传入派生类名称,(temporary_class,) 作为 this_bases 参数。预期元类 meta 然后用于调用 meta.__prepare__() ,忽略 this_bases 并传入 bases 参数。
  • 接下来,在使用 metaclass.__prepare__() 的返回值作为类属性的基本命名空间(或者在 Python 2 上仅使用普通字典)之后,Python 调用 metaclass.__new__() 来创建实际类。这再次作为 (temporary_class,) 元组传递 this_bases,但上面的代码忽略了这一点并使用 bases 代替,调用 meta(name, bases, d) 来创建新的派生类。

因此,使用 with_metaclass() 为您提供了一个新的类对象没有额外的基类:

>>> class FooMeta(type): pass
...
>>> with_metaclass(FooMeta) # returns a temporary_class object
<class '__main__.temporary_class'>
>>> type(with_metaclass(FooMeta)) # which has a custom metaclass
<class '__main__.metaclass'>
>>> class Foo(with_metaclass(FooMeta)): pass
...
>>> Foo.__mro__ # no extra base classes
(<class '__main__.Foo'>, <type 'object'>)
>>> type(Foo) # correct metaclass
<class '__main__.FooMeta'>

关于Python 元类 : Understanding the 'with_metaclass()' ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18513821/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com