Python 中的元类是什么?

源码货栈 论文问答 1

什么是元类,我们用它们做什么?

回复

共2条回复 我来回复
  • 源码港湾
    这个人很懒,什么都没有留下~
    评论

    元类是类的类。就像类定义类的实例的行为方式一样,元类定义类的行为方式。类是元类的一个实例。

    虽然在 Python 中,您可以对元类使用任意可调用对象(如 Jerub 所示),但更有用的方法实际上是使其本身成为一个实际的类。 type 是 Python 中常用的元类。如果您想知道,是的, type 它本身就是一个类,它是它自己的类型。您将无法重新创建 type 纯粹在 Python 中的东西,但 Python 会作弊。要在 Python 中创建自己的元类,你真的只想继承 type .

    元类最常用作类工厂。就像您通过调用类来创建类的实例一样,Python 通过调用元类来创建一个新类(当它执行“类”语句时)。结合普通 __init__ __new__ 方法,元类因此允许您在创建类时做“额外的事情”,例如使用某个注册表注册新类,甚至完全用其他东西替换该类。

    执行语句时 class ,Python 首先将 class 语句体作为普通代码块执行。生成的命名空间(一个字典)保存了类的属性。元类是通过查看待定类的基类(继承元类)、待定类的 __metaclass__ 属性(如果有)或 __metaclass__ 全局变量来确定的。然后使用类的名称、基类和属性调用元类以实例化它。

    然而,元类实际上定义了一个类的 类型 ,而不仅仅是它的工厂,所以你可以用它们做更多的事情。例如,您可以在元类上定义普通方法。这些元类方法类似于类方法,因为它们可以在没有实例的类上调用,但它们也不像类方法,因为它们不能在类的实例上调用。是元类 type.__subclasses__() 上的方法的示例。 type 您还可以定义普通的“魔术”方法,如和 __add__ ,以实现或更改类的行为方式。 __iter__``__getattr__

    演示:

    def make_hook(f):
        """Decorator to turn 'foo' method into '__foo__'"""
        f.is_hook = 1
        return f
    
    class MyType(type):
        def __new__(mcls, name, bases, attrs):
    
            if name.startswith('None'):
                return None
    
            # Go over attributes and see if they should be renamed.
            newattrs = {}
            for attrname, attrvalue in attrs.iteritems():
                if getattr(attrvalue, 'is_hook', 0):
                    newattrs['__%s__' % attrname] = attrvalue
                else:
                    newattrs[attrname] = attrvalue
    
            return super(MyType, mcls).__new__(mcls, name, bases, newattrs)
    
        def __init__(self, name, bases, attrs):
            super(MyType, self).__init__(name, bases, attrs)
    
            # classregistry.register(self, self.interfaces)
            print "Would register class %s now." % self
    
        def __add__(self, other):
            class AutoClass(self, other):
                pass
            return AutoClass
            # Alternatively, to autogenerate the classname as well as the class:
            # return type(self.__name__ + other.__name__, (self, other), {})
    
        def unregister(self):
            # classregistry.unregister(self)
            print "Would unregister class %s now." % self
    
    class MyObject:
        __metaclass__ = MyType
    
    
    class NoneSample(MyObject):
        pass
    
    # Will print "NoneType None"
    print type(NoneSample), repr(NoneSample)
    
    class Example(MyObject):
        def __init__(self, value):
            self.value = value
        @make_hook
        def add(self, other):
            return self.__class__(self.value + other.value)
    
    # Will unregister the class
    Example.unregister()
    
    inst = Example(10)
    # Will fail with an AttributeError
    #inst.unregister()
    
    print inst + inst
    class Sibling(MyObject):
        pass
    
    ExampleSibling = Example + Sibling
    # ExampleSibling is now a subclass of both Example and Sibling (with no
    # content of its own) although it will believe it's called 'AutoClass'
    print ExampleSibling
    print ExampleSibling.__mro__
    
    0条评论
  • 毕设工厂
    这个人很懒,什么都没有留下~
    评论

    在我编写的测试框架中,我想跟踪定义类的顺序,以便以后可以按此顺序实例化它们。我发现使用元类最容易做到这一点。

    class MyMeta(type):
    
        counter = 0
    
        def __init__(cls, name, bases, dic):
            type.__init__(cls, name, bases, dic)
            cls._order = MyMeta.counter
            MyMeta.counter += 1
    
    class MyType(object):              # Python 2
        __metaclass__ = MyMeta
    
    class MyType(metaclass=MyMeta):    # Python 3
        pass
    

    任何作为 MyType then 子类的东西都会获得一个类属性,该属性 _order 记录了定义类的顺序。

    0条评论

发表回复

登录后才能评论