什么是 python 中的元类
所属网站分类: python 高级>面向对象
作者: goodbody
元类是类的类. 就像类定义了类的实例的行为一样, 元类定义了类的行为方式. 类是元类的实例.
虽然在 Python 中你可以为元类使用任意的 callables, 实际上更有用的方法是使它成为一个真正的类本身.
type 是 Python 中常用的元类. type 它本身就是一个类, 它是它自己的类型.
你将无法使用 type 在 Python 中重新创建纯粹的东西.
元类最常用作类工厂. 就像通过调用类创建类的实例一样, Python 通过调用元类创建了一个新类(当它执行'class'语句时). 结合__init__和__new__方法, 元类因此允许您在创建类时执行 "额外的事情", 例如使用某个注册表注册新类, 或者甚至完全用其他内容替换类.
元类是通过查看待定类的基类 (继承的元类),__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__
来源: https://www.2cto.com/kf/201905/809336.html