Python 类的创建方式
了解 type、默认元类和类创建钩子。
Python 类的创建方式 是 CoddyKit 上的免费 Python Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。
type() 是元类
Python 中的每个类都是 type 的实例。type 本身也是一个类——它是所有元类的元类。
# These are equivalent:
class Dog:
sound = "woof"
Dog2 = type("Dog2", (), {"sound": "woof"})
print(type(Dog)) # <class 'type'>
print(type(Dog2)) # <class 'type'>type() 的三参数形式
type(name, bases, namespace) 会动态创建一个新类。这正是 class 语句在底层执行的操作。
Animal = type("Animal", (), {"speak": lambda self: "..."})
Dog = type("Dog", (Animal,), {"speak": lambda self: "woof"})
d = Dog()
print(d.speak()) # woof类创建步骤
当 Python 遇到 class 语句时,会依次执行:1)解析元类;2)准备命名空间;3)执行类体;4)调用 metaclass(name, bases, namespace)。
# class Foo(Base, metaclass=Meta):
# x = 1
#
# Equivalent to:
# namespace = Meta.__prepare__("Foo", (Base,))
# exec(class_body, namespace)
# Foo = Meta("Foo", (Base,), namespace)__prepare__
__prepare__(name, bases, **kw) 是元类上的类方法,会返回用于执行类体的命名空间字典。重写它可以使用 OrderedDict 或自定义映射。
class OrderedMeta(type):
@classmethod
def __prepare__(mcs, name, bases, **kw):
print(f"Preparing namespace for {name}")
return {}
class MyClass(metaclass=OrderedMeta):
x = 1
y = 2type 中的 __new__ 与 __init__
type.__new__ 创建类对象;type.__init__ 对其进行初始化。对于元类,请重写 __new__ 来定制类的创建过程。
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kw):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kw)
return cls._instances[cls]
class DB(metaclass=Singleton):
pass
print(DB() is DB()) # True类装饰器与元类
类装饰器在创建完成后应用;元类控制创建过程本身。对于简单的增强,优先使用装饰器。需要影响创建过程时,请使用元类。
def add_repr(cls):
cls.__repr__ = lambda self: f"{cls.__name__}()"
return cls
@add_repr
class Widget:
pass
print(Widget()) # Widget()__init_subclass__
每当定义子类时,基类都会调用 __init_subclass__。对于定制子类行为,这是元类的一种轻量替代方案。
class Plugin:
_registry = []
def __init_subclass__(cls, **kw):
super().__init_subclass__(**kw)
Plugin._registry.append(cls)
class AudioPlugin(Plugin): pass
class VideoPlugin(Plugin): pass
print(Plugin._registry) # [AudioPlugin, VideoPlugin]ABCMeta
ABCMeta 是一个内置元类,通过 @abstractmethod 支持抽象基类。
from abc import ABCMeta, abstractmethod
class Shape(metaclass=ABCMeta):
@abstractmethod
def area(self): ...
class Circle(Shape):
def __init__(self, r): self.r = r
def area(self): return 3.14159 * self.r ** 2
# Shape() # TypeError: Can't instantiate abstract class检查类的元类
使用 type(cls) 查找类的元类,并使用 cls.__mro__ 查看方法解析顺序。
class Meta(type): pass
class Foo(metaclass=Meta): pass
print(type(Foo)) # <class '__main__.Meta'>
print(Foo.__mro__) # (Foo, object)元类继承
类的元类会被其子类继承。如果两个基类具有不同的元类,则必须使用派生程度最高的元类,否则会出现 conflict。
class MyMeta(type): pass
class Base(metaclass=MyMeta): pass
class Child(Base): pass # Child's metaclass is also MyMeta
print(type(Child)) # <class '__main__.MyMeta'>何时使用元类
在以下情况下可以使用元类:自动注册子类、强制执行类不变量、检测 ORM 字段(例如 Django 的模型)以及处理 API 框架路由。对于大多数情况,请改用 __init_subclass__ 或类装饰器。
# Real-world: Django ORM uses ModelBase metaclass
# to collect field definitions into _meta
# You rarely need a custom metaclass;
# __init_subclass__ covers most plugin/registration patterns快速检查
type("Dog", (Animal,), {"speak": lambda self: "woof"}) 会做什么?
回顾
每个类都是 type 的实例。类创建流程为:解析元类 → 准备命名空间 → 执行类体 → 调用元类。对于简单的子类钩子,请优先使用 __init_subclass__;只有需要控制类创建本身时,才使用完整的元类。
常见问题解答
「Python 类的创建方式」课时是免费的吗?
是的 — 「Python 类的创建方式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。
「Python 类的创建方式」这节课中我会学到什么?
了解 type、默认元类和类创建钩子。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Python Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「Python 类的创建方式」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Python Academy 课中编写并运行代码吗?
能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- Python 类的创建方式
- 编写自定义元类
- 描述器:__get__、__set__、__delete__
- __slots__ 与内存优化