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:快速生成 __init__/repr/eq 等,适合“数据载体”;配合 frozen=True 可做不可变值对象。
- namedtuple:更轻、更偏“tuple 语义”,适合只读小结构、需要解包/位置语义的场景。
- 普通类:当你需要复杂行为、校验、继承、多态时更合适。
- 追问点:dataclass 的默认可变字段坑(例如 list 默认值)要用 default_factory。
7:Python 的 import 机制?循环导入怎么破?
回答要点:
- import 会先查 sys.modules 缓存;同一个模块只会初始化一次,后续是复用引用。
- 循环导入常见表现:属性不存在、模块处于“半初始化状态”。
- 解决思路:
- 拆分公共依赖到第三个模块
- 延迟导入(在函数内部 import)
- 调整依赖方向(让底层模块不 import 上层模块)
8:logging 怎么用才算“线上可排障”?不要只说“我会 print”
回答要点:
- 线上日志至少要能回答三件事:谁(trace/request id)、在哪(模块/函数)、发生了什么(结构化字段)。
- 常见落地:
- 用 logging 的 logger 分级(INFO/WARN/ERROR),不要全用 print。
- 异常用 logger.exception(…) 保留堆栈。
- 关键链路打点要“结构化”(字段化),便于检索聚合(而不是拼接大长字符串)。


