Python Metaclass:理解'with_metaclass()'

Zak*_*kos 48 python metaclass six-python

我想问一下这个with_metaclass()调用在一个类的定义中意味着什么.

例如:

class Foo(with_metaclass(Cls1, Cls2)):
Run Code Online (Sandbox Code Playgroud)
  • 是一个特殊的情况,一个类继承了元类?
  • 新类也是元类吗?

Mar*_*ers 74

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

它为您创建一个带有指定元类的基类,与您运行代码的Python版本兼容.

引用文档:

使用基类base和元类metaclass创建一个新类.这被设计用于类声明,如下所示:

from six import with_metaclass

class Meta(type):
    pass

class Base(object):
    pass

class MyClass(with_metaclass(Meta, Base)):
    pass
Run Code Online (Sandbox Code Playgroud)

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

Python 2:

class MyClass(object):
    __metaclass__ = Meta
Run Code Online (Sandbox Code Playgroud)

Python 3:

class MyClass(metaclass=Meta):
    pass
Run Code Online (Sandbox Code Playgroud)

with_metaclass()函数利用了元类是a)由子类继承的事实,以及b)元类可用于生成新类; 它通过使用元类作为工厂生成一个空类来有效地创建一个新的基类:

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', (), {})
Run Code Online (Sandbox Code Playgroud)

metaclass基类的元类是type.__new__(metaclass, 'temporary_class', (), {}),无论在Python 2和3.

  • 只是为了澄清六,语法(以匹配上面的python 2和3的行为):`class MyClass(with_metaclass(Meta,object)):pass`(其中对象是可选的). (2认同)

pyl*_*ang 24

更新:该six.with_metaclass()函数已经用装饰器变体修补,即@six.add_metaclass().此更新修复了与基础对象相关的一些mro问题.新装饰器将按如下方式应用:

import six

@six.add_metaclass(Meta)
class MyClass(Base):
    pass
Run Code Online (Sandbox Code Playgroud)

以下是补丁说明,这里是使用装饰器替代方案的类似详细示例和说明.