在Python中,元类是什么?

内容来自 DOC https://q.houxu6.top/?s=在Python中,元类是什么?

什么是元类(metaclasses)?它们用于什么目的?

元类是Python中的一种高级概念,它们是创建类的类。在Python中,类也是对象,因此它们也可以被看作是对象的模板。元类允许您控制类的创建过程,例如修改类的属性或方法,或者添加新的属性和方法。

元类通常用于以下目的:

  • 动态地创建类。您可以使用元类在运行时创建新的类,而不是在编写代码时静态地定义它们。
  • 修改类的行为。您可以使用元类来修改类的行为,例如添加新的属性或方法,或者修改现有属性或方法的行为。
  • 实现插件系统。您可以使用元类来实现插件系统,这样您就可以在不修改现有代码的情况下向应用程序添加新功能。

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

虽然在Python中可以使用任意可调用对象作为元类(如Jerub所示),但更好的方法是将其本身变成一个实际的类。type是Python中通常的元类。type本身就是一个类,它是它自己的类型。您无法完全用Python重新创建类似type的东西,但Python有点作弊。要在Python中创建自己的元类,您真正想要做的只是继承type

元类最常用于类工厂。当您通过调用类来创建对象时,Python会在执行'class'语句时通过调用元类来创建一个新的类。与正常的__init____new__方法结合使用,元类因此允许在创建类时执行“额外的事情”,例如将新类注册到某些注册表中或将类替换为完全不同的东西。

当执行'class'语句时,Python首先将'class'语句的主体作为常规代码块执行。结果命名空间(字典)包含要创建的类的属性。元类是通过查看要创建的类的基类(元类是继承的)、要创建的类的__metaclass__属性(如果有)或__metaclass__全局变量来确定的。然后,使用要实例化的类的名称、基类和属性调用元类。

然而,元类实际上定义了一个type的类,而不仅仅是它的工厂,因此您可以使用它们做更多的事情。例如,您可以在元类上定义普通方法。这些元类方法类似于类方法,可以在没有实例的情况下调用类,但它们也不像类方法那样可以在类的实例上调用。type.__subclasses__()type元类上的一个方法示例。您还可以定义普通的“魔术”方法,例如__add____iter____getattr__,以实现或更改类的行为。

以下是一些零碎的例子:

def make_hook(f):
    """装饰器将'foo'方法变成'_\_foo\_\_'"""
    f.is_hook = 1
    return f

class MyType(type):
    def __new__(mcls, name, bases, attrs):

        if name.startswith('None'):
            return None

        # 遍历属性,看看它们是否应该被重命名。
        newattrs = {}
        for attrname, attrvalue in attrs.items():
            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
        # 或者,自动生成类名以及类:
        # 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

# 将打印 "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)

# 将取消注册类
Example.unregister()

inst = Example(10)
# 将引发AttributeError错误
#inst.unregister()

print(inst + inst)
class Sibling(MyObject):
    pass

ExampleSibling = Example + Sibling
# ExampleSibling现在是Example和Sibling的子类(没有自己的内容)
# 尽管它会认为它被称为'AutoClass'
print(ExampleSibling)
print(ExampleSibling.__mro__)
posted @ 2023-10-07 20:40  小满独家  阅读(52)  评论(0)    收藏  举报