__dir__是唯一被IDE和REPL主动调用以提供补全建议的魔术方法,它只影响dir()输出和补全提示,不改变实际属性访问;必须返回纯字符串列表,否则补全可能失效。

直接说结论: __dir__ 是 Python 中唯一能被 IDE 和 REPL 主动调用以获取补全建议的魔术方法,但它不改变实际属性访问行为,只影响 dir() 和补全提示——想让补全“看起来对”,就得让它返回你真正想暴露的字符串列表。
为什么 __dir__ 返回的列表必须全是字符串?
因为 dir() 的规范定义就是返回一个 list[str],IDE(如 VS Code、PyCharm)和 IPython 都严格按这个约定解析。如果返回了 int、None 或嵌套结构,会静默忽略非法项,甚至导致整个补全失效。
- ✅ 正确:
return ["foo", "bar", "_internal_helper"] - ❌ 错误:
return [self.foo, 42](类型错)、return {"foo": "val"}(非列表) - ⚠️ 注意:
__dir__不需要包含所有真实存在的属性——它只是“建议列表”,Python 仍会按常规 MRO 查找实际可访问的属性
如何让 __dir__ 动态响应实例状态?
很多场景下,可用属性取决于初始化参数或运行时状态(比如配置类、代理对象)。这时不能只写死 return dir(super()) + [...] ,得主动构造。
- 用
getattr(self, "_available_fields", [])这类约定字段控制补全范围 - 避免在
__dir__里做耗时操作(如网络请求、文件读取),补全触发频繁,卡顿会非常明显 - 示例:一个只暴露已注册 handler 的类
class PluginManager:
def __init__(self):
self._handlers = {}
<pre class="brush:php;toolbar:false;">def register(self, name: str, func):
self._handlers[name] = func
def __dir__(self):
# 合并父类默认 + 当前注册的 handler 名
return list(set(dir(super())) | set(self._handlers.keys()))
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
常见补全失效的三个坑
即使写了 __dir__,补全也可能不出现——多数是环境或实现细节没对齐。
- IDE 缓存未刷新:改完
__dir__后重启 Python 解释器或重载模块(importlib.reload()),否则旧缓存还在 - 类继承了
typing.Protocol或用了@dataclass(slots=True):这些机制可能绕过__dir__,需显式在子类中重写并调用super().__dir__() - IPython 中未启用自动补全:确认
%config IPCompleter.use_jedi = True(Jedi 才识别__dir__)
最常被忽略的一点:补全列表里混入私有名称(如 _helper)确实会出现,但用户是否看到,还取决于 IDE 的“显示私有成员”设置——这层过滤发生在 __dir__ 之后,你无法控制。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










