核心梗概如果说类是模具实例是模具造出的产品那么元类就是制造模具的那台“机床”。今天带你当一回女娲手搓泥人类。1. 惊不惊喜类本身也是个“对象”很多初学 Python 的朋友会把“一切皆对象”挂在嘴边但往往只理解了一半。我们通常认为p1 Person()p1是对象。但你可曾想过Person这个类本身也是某个“东西”造出来的对象class Person: pass p1 Person() print(type(p1)) # class __main__.Person 实例的类型是类 print(type(Person)) # class type 类的类型是 type没错Person这个类是type这个“元类”的一个实例。就像p1有属性name一样Person也有自己的属性如__name__,__bases__。type就是 Python 世界里所有类的“老祖宗”。2. 不用class关键字照样造类很多人用了几年 Python写了几百个class却不知道class只是语法糖。实际上我们完全可以手撸type构造函数来动态创建一个类# 用 type 创建了一个“活生生”的类 MyDynamicClass type(MyDynamicClass, (object,), { species: Human, say_hello: lambda self: print(Hello from dynamic class!) }) obj MyDynamicClass() print(obj.species) # Human obj.say_hello() # Hello from dynamic class!这就好比你不用图纸class 关键字直接拿着钢铁type 函数在现场锻造出一个机器人。这在写框架比如 Django ORM时极其有用因为数据库的表结构是运行时才知道的。3. 自定义元类给类创建加个“拦截器”真正的黑科技来了如果我们继承type重写里面的__new__方法就等于在类诞生的那一刹那产房门口拦截住了这个“新生儿”我们想怎么改就怎么改——改名字、改父类、强行加文档、加类属性。结合你提供的100.元类.py代码我们来点更生动的场景假如你是一个严格的代码规范管理员你想让公司所有的新类都自动带上你的工牌后缀并且强制必须有文档字符串顺便再给它们加个超能力比如混入一个颜色类。import pygame class BossMeta(type): 老板级元类凡是经过我手里创建的类都得听我安排 def __new__(cls, name, bases, attrs): # 1. 强制改名不管开发者写什么类名我都给你加上公司后缀 name name.capitalize() _Company_Inc # 2. 强制继承不管你原来继承谁我都给你硬塞一个 pygame.Color 的能力 bases bases (pygame.Color,) # 3. 强制写文档如果程序员偷懒没写文档我来给他补上 if __doc__ not in attrs or not attrs[__doc__]: attrs[__doc__] f此乃 {name} 专属类未经允许不得修改 # 4. 全员加薪每个类都有 100 岁寿命MAX_AGE attrs[MAX_AGE] 100 # 5. 最后调用亲爹 type 的 __new__ 真正把类生出来 return type.__new__(cls, name, bases, attrs) # 程序员张三写了一个类浑然不知会被老板改造 class Person(metaclassBossMeta): pass # 张三一看打印结果傻眼了 print(Person.__name__) # Person_Company_Inc 名字被改了 print(Person.__bases__) # (class object, class pygame.Color) 多了个爹 print(Person.__doc__) # 此乃 Person_Company_Inc 专属类未经允许不得修改 print(Person.MAX_AGE) # 100 白捡的属性总结元类就是 Python 的“天条”。用得好你就是如来佛祖框架级的代码规整得服服帖帖用不好那就是太上老君的炼丹炉容易把自己烧死调试难度极大。记住除非你要写框架否则别轻易玩火。