python-什么是Python中的元类?

发布于 2021-02-02 23:24:51

元类是什么,我们将它们用于什么?

关注者
0
被浏览
304
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    元类是类的类。类定义类的实例(即对象)的行为,而元类定义类的行为。类是元类的实例。

    虽然在Python中你可以对元类使用任意可调用对象(例如Jerub演示),但是更好的方法是使其成为实际的类。type是Python中常见的元类。type它本身是一个类,并且是它自己的类型。你将无法type纯粹使用Python 重新创建类似的东西,但是Python有点作弊。要在Python中创建自己的元类,你实际上只想将其子类化type

    元类最常用作类工厂。当你通过调用类创建对象时,Python通过调用元类来创建一个新类(执行“ class”语句时)。因此,与普通方法__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__
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看