AI智能
改变未来

每天一道 python 面试题 – Python中的元类(metaclass)

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

虽然在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)

       # cla***egistry.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):
       # cla***egistry.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) 打赏
未经允许不得转载:爱站程序员基地 » 每天一道 python 面试题 – Python中的元类(metaclass)