Skip to content

类与元编程

property、__slots__、dataclass、元类(了解级)。

Updated View as Markdown
For humans

类与元编程

面试主线分三层:日常必用的 property 和 slots,提高效率的 dataclass,以及了解级的元类(能说出用途即可,不要求手写)。

property:属性即方法

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def area(self):            # 读: 像属性一样访问
        return 3.14 * self._radius ** 2

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):   # 写: 校验入口
        if value <= 0:
            raise ValueError("半径必须为正")
        self._radius = value
  • 把方法包装成属性访问,调用方无感知(c.area 不是 c.area()
  • setter 是校验和副作用的最佳位置:统一在赋值处拦截非法值
  • 只定义 getter 不定义 setter 就是只读属性
  • 本质是装饰器 + 描述符协议

slots:省内存

class Point:
    __slots__ = ("x", "y")     # 固定属性名
    def __init__(self, x, y):
        self.x, self.y = x, y
  • 默认类有 __dict__(属性字典),每个实例都带一个字典,内存开销大
  • __slots__ 声明固定属性,实例用紧凑的数组存属性,省内存(大量实例时明显,如数据对象)
  • 代价:不能动态加属性(没有 dict)、多重继承有限制
  • 适用:百万级实例的数据类。普通业务类不需要

dataclass:数据类

from dataclasses import dataclass, field

@dataclass
class User:
    id: int
    name: str
    tags: list[str] = field(default_factory=list)   # 可变默认值正确写法
  • 自动生成 __init____repr____eq__,减少样板代码
  • frozen=True 生成不可变数据类(可哈希,配 @dataclass(frozen=True, order=True) 更全)
  • field(default_factory=...) 处理可变默认值(见函数篇的 None 陷阱同源问题)
  • 数据建模首选 dataclass,需要校验和序列化时换 Pydantic

元类:了解级

元类(metaclass)是“创建类的类”。class 语句的执行流程:

  1. 解释器调用元类(默认 type
  2. type.__new__ 创建类对象(名字、基类、命名空间)
  3. type.__init__ 初始化类
class SingletonMeta(type):      # 元类示例: 拦截类创建
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

知道什么场景用:在类创建时统一注入行为,如 ORM 的模型注册(SQLAlchemy Declarative)、框架的类级配置、注册表模式。业务代码几乎不用,面试答到“元类是类的类,用于类创建时拦截,典型如 ORM 注册机制”即可。

面试追问

  1. property 解决什么? 方法当属性访问,setter 统一校验。调用方无感知,接口稳定
  2. slots 有什么用? 省内存:去掉实例 dict,属性存紧凑数组。代价是不能动态加属性
  3. dataclass 和普通类的区别? 自动生成 init/repr/eq。frozen 不可变,default_factory 处理可变默认值
  4. 元类是什么? 创建类的类。class 语句由元类执行。用途:类创建时统一处理(ORM 注册、单例)
  5. 什么时候用元类? 框架开发。业务代码用装饰器和描述符更简单,元类是兜底手段
Navigation

Type to search…

↑↓ navigate↵ selectEsc close