Python的元模型究竟是如何构建出如此丰富的功能的?

摘要:虽然Python作为AI领域的第一语言,但是作为一个C#的深度使用者,对于Python这门编程语言确实有太多值得吐槽的地方。但是我觉得Python在设计上有一个绝对的亮点,也是我最喜欢的地方,那就是基于元类的元模型,在这篇文章中我会聊聊我对
虽然Python作为AI领域的第一语言,但是作为一个C#的深度使用者,对于Python这门编程语言确实有太多值得吐槽的地方。但是我觉得Python在设计上有一个绝对的亮点,也是我最喜欢的地方,那就是基于元类的元模型,在这篇文章中我会聊聊我对Python元模型理解。 1. 元宇宙类比 我们以前两年风光无限,现今基本无人提及的元宇宙来类比。从“创世”的角度来讲,元宇宙定义了宇宙(现实世界)的法则,宇宙是由元数据构建的一个实例。“元”和“实例”并非决定概念,元宇宙也是宇宙,元宇宙的法则由更高层次的“元元宇宙”来定义,元宇宙就是这个元元宇宙的实例。以此类推,不断抽象,直至尽头,在那里我们找不到法则的来源,于是有人将其视为“造物主”,老子将其称为“道”,我们不妨将这个宇宙称为创世宇宙。我们找不到创世宇宙的元,于是我们它自己作为自己的元,这样便形成一个自洽的闭环。既然我们将宇宙视为其元宇宙的实例,那么创世宇宙的实例也包含它自己。 元可以比实例更简单,所谓大道至简,“道生一、一生二、二生三、三生万物”即为这个道理。元也可以比实例更复杂,它可以包含纷繁复杂的法则,我们只取其部分法则来构建实例。看过《完美世界》都知道,“下界八域”作为作为囚犯的放逐之地,是一个以“上界”为元宇宙构建的“降维宇宙”,由于法则不全,在下界修炼的境界只能达到“尊者境”,不能成神。 在Python的“元宇宙”也是如此,我们使用元为实例定义规则,并作为创建实例的工厂,所以类为实例的元。我们可以使用元类创建类,所以常规类是元类的实例,元类是常规类的元。从这个意义上将,元类叫类元可能更贴切,但是元类除了表达“类的元”外,还体现了元类也是类的概念。既然元类是类,自然也可以有自己的元类。所以类即元,元亦是类,正如“元宇宙也是宇宙,宇宙亦可作为元宇宙”。 Python的创世宇宙是type,我们的类由它构建,所以type是类的元类。既然type是元类,所以type也具有类的属性。由于处在创世宇宙这个超然的位置,type可以视为type的实例。 2. 元类的定义 在默认情况下,我们使用一个类去构建实例的时候,背后的流程是: 将类和参数(含任意添加的关键字参数)传入类的__new__方法创建一个基础对象; 将这个基础对象和参数传入类的__init__方法进行初始化; 但会这个经过初始化的对象; 所以针对如下定义的Foobar类,两种创建实例(foobar1和foobar2)的方式是等效的。这里强调以下,虽然就定义看起来__new__方法像一个类方法,但是它本质上时一个静态方法。在它之上既没有标准@classmethod装饰器,调用的时候第一个参数也也必须指定。 from typing_extensions import Self from typing import Any class Foobar: def __new__(cls, *args: Any, **kwargs: Any) -> Self: return super().__new__(cls) def __init__(self, foo: int, bar: int) -> None: self.foo = foo self.bar = bar def __eq__(self, value: object) -> bool: if not isinstance(value, Foobar): return NotImplemented return self.foo == value.foo and self.bar == value.bar foobar1 = Foobar(foo=111, bar=222) foobar2 = Foobar.__new__(Foobar, foo=111, bar=222) Foobar.__init__(foobar2, foo=111, bar=222) assert foobar1 == foobar2 与之类似,元类作为一个类,它也可以定义__new__和__init__方法。类的这两个方法是为了初始化它的实例,元类的这两个方法的使命也是如此,只是元类的实例是以它为元类的类罢了。
阅读全文