Python元类:了解"with_metaclass()" [英] Python Metaclass : Understanding the 'with_metaclass()'

查看:282
本文介绍了Python元类:了解"with_metaclass()"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to ask what the with_metaclass() call means in the definition of a class.

例如:

class Foo(with_metaclass(Cls1, Cls2)):

  • 类是从元类继承的特殊情况吗?
  • 新类也是元类吗?
  • 推荐答案

    with_metaclass() six提供的实用程序类工厂函数,以简化为两个Python 2开发代码的过程和3.

    with_metaclass() is a utility class factory function provided by the six library to make it easier to develop code for both Python 2 and 3.

    使用一个临时元类需要一点点的手(见下文),以一种与Python 2和Python 3交叉兼容的方式将元类附加到常规类.

    It uses a little slight of hand (see below) with a temporary metaclass, to attach a metaclass to a regular class in a way that's cross-compatible with both Python 2 and Python 3.

    从文档中引用:

    使用基类base和metaclass元类创建一个新类.旨在用于此类的类声明中:

    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之间已更改.

    This is needed because the syntax to attach a metaclass changed between Python 2 and 3:

    Python 2:

    class MyClass(object):
        __metaclass__ = Meta
    

    Python 3:

    class MyClass(metaclass=Meta):
        pass
    

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

    The with_metaclass() function makes use of the fact that metaclasses are a) inherited by subclasses, and b) a metaclass can be used to generate new classes and c) when you subclass from a base class with a metaclass, creating the actual subclass object is delegated to the metaclass. It effectively creates a new, temporary base class with a temporary metaclass metaclass that, when used to create the subclass swaps out the temporary base class and metaclass combo with the metaclass of your choice:

    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__()来创建实际的类.再次将它作为this_bases元组传递给(temporary_class,),但是上面的代码忽略了它,而是使用bases来调用meta(name, bases, d)来创建新的派生类.
    • type.__new__(metaclass, 'temporary_class', (), {}) uses the metaclass metaclass to create a new class object named temporary_class that is entirely empty otherwise. type.__new__(metaclass, ...) is used instead of metaclass(...) to avoid using the special metaclass.__new__() implementation that is needed for the slight of hand in a next step to work.
    • In Python 3 only, when temporary_class is used as a base class, Python first calls metaclass.__prepare__() (passing in the derived class name, (temporary_class,) as the this_bases argument. The intended metaclass meta is then used to call meta.__prepare__(), ignoring this_bases and passing in the bases argument.
    • next, after using the return value of metaclass.__prepare__() as the base namespace for the class attributes (or just using a plain dictionary when on Python 2), Python calls metaclass.__new__() to create the actual class. This is again passed (temporary_class,) as the this_bases tuple, but the code above ignores this and uses bases instead, calling on meta(name, bases, d) to create the new derived class.

    因此,使用with_metaclass()将为您提供一个新的类对象,而没有其他基类:

    As a result, using with_metaclass() gives you a new class object with no additional base classes:

    >>> 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元类:了解"with_metaclass()"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆