1. __slots__ 是什么?它解决什么问题?有什么坑?
__slots__可以限制实例属性集合,避免每个对象都带一个__dict__,从而减少内存占用、提高属性访问性能(在大量小对象场景更明显)。- 常见坑:
- 加了
__slots__后不能随便新增属性(除非 slot 里声明了)。 - 如果类需要弱引用,要在 slots 里加
__weakref__。 - 继承时要小心:子类 slots 叠加规则、以及是否保留父类
__dict__。
- 加了
2. __getattr__ vs __getattribute__ 有什么区别?什么时候会无限递归?
__getattribute__:所有属性访问都会先走它;你在里面写错很容易把对象变成'不可用'。__getattr__:只在正常查找失败(属性不存在)时才会调用,通常更安全。- 无限递归典型原因:在
__getattribute__里又用self.xxx访问属性,触发再次进入__getattribute__。正确写法一般是用object.__getattribute__(self, name)拿底层实现。
3. @property 和 descriptor(描述符)你怎么解释?它们和'方法/字段'到底有什么关系?
@property让你用'访问属性'的语法去调用 getter/setter,本质是 descriptor(实现了__get__/__set__/__delete__的对象)。- 你需要讲清楚的一点:Python 里'属性访问'不是直接读字段,可能触发 descriptor、
__getattribute__、甚至动态计算。 - 追问点:
@property适合做校验/惰性加载/只读字段,但别把重计算塞进去(会让属性访问变成隐藏的慢操作)。
4. global 和 nonlocal 的区别?闭包变量到底存在哪?
global:声明变量来自模块全局作用域。nonlocal:声明变量来自最近一层的外部函数作用域(闭包)。- 追问点:为什么要有
nonlocal?因为闭包里对外层变量赋值默认会创建局部变量,nonlocal才能修改外层绑定。
5. __hash__ 和 __eq__ 的契约是什么?为什么'自定义对象当 dict key'经常出问题?
- 作为 dict key / set 元素必须是 hashable:
hash(x)在对象生命周期内要稳定。 - 关键契约:如果
a == b,那么必须hash(a) == hash(b),否则哈希容器行为就会错(查不到、重复、丢失等)。 - 常见坑:你重写了
__eq__但没重写__hash__,Python 会把它变成不可 hash(防止你误用)。
6. dataclass/namedtuple/普通类 怎么选?你怎么解释它们的取舍?
dataclass:快速生成 等,适合'数据载体';配合 可做不可变值对象。


