??能成功显示源码的前提是函数由Python编写、源文件可访问且未被C扩展完全隐藏;否则仅显示签名和docstring。

用 ?? 查看函数源码,什么情况下能成功?
?? 能显示源码的前提是:该函数由 Python 编写、源文件可访问、且未被编译器或 C 扩展完全隐藏。内置函数(如 len、print)或用 C 实现的 NumPy/Pandas 核心方法(如 np.array、pd.DataFrame.sort_values)调用 ?? 只会显示签名和 docstring,不会出现源码——因为底层压根不是 Python 写的。
常见能看源码的场景包括:
- 你自己定义的函数(
def my_func(x): return x ** 2) - 第三方包中纯 Python 实现的工具函数(如
scikit-learn里的check_array) - 带完整 docstring 和明确
def块的类方法(如pandas.Series.dropna的部分封装层)
?? 和 ? 的关键区别在哪?
? 只触发 %pinfo,输出结构化元信息:签名、docstring(按 numpy/google 格式解析后的参数表)、模块路径、定义行号;?? 在此基础上叠加 %pinfo2 + 源码提取逻辑,会尝试读取 inspect.getsource() 返回的内容。
注意两个细节:
- 如果函数被装饰器包裹(比如
@lru_cache或自定义装饰器),??默认展示的是装饰后对象,可能看不到原始def——此时需加%pinfo2 func看继承链和真实绑定位置 - 某些动态生成的函数(如
functools.partial或 lambda)不支持??,会报TypeError: <lambda> is not a Python function</lambda>
为什么有时 ?? 显示 “Source: Not available”?
这不是命令失效,而是 IPython 检查到以下任一条件成立:
- 函数来自已编译的扩展模块(
.so/.pyd),例如cv2.imread - 源码被剥离(如 conda 安装的某些包只含字节码
.pyc) - 函数是通过
exec()或eval()动态构造的,没有对应磁盘文件 - 当前 Python 进程无权限读取源文件路径(少见,多见于容器或受限环境)
此时可退而求其次:func? 看文档 + func.__code__.co_filename 查路径 + 手动打开文件定位;若连 __code__ 都不可用,说明它根本不是标准 Python 函数。
替代方案:当 ?? 失效时还能做什么?
别卡在“看不到源码就无法理解”的思维里。实际调试中更高效的做法是:
- 用
help(func)获取权威参数说明(尤其对 C 扩展函数,help 文档常比在线 API 更准) - 查模块
__file__:如import numpy; print(numpy.__file__),定位安装路径后去 GitHub 搜对应函数名 - 在 Jupyter 中执行
%pinfo2 func,它会列出所有属性、方法、内存地址,有时能发现未导出但可用的辅助函数 - 对 pandas/scikit-learn 等主流库,直接访问其 GitHub 仓库(如
github.com/pandas-dev/pandas/blob/main/pandas/core/frame.py),Ctrl+F 搜索函数名更快
真正容易被忽略的是:很多“看不懂的行为”,其实源于参数默认值或内部状态(比如 sklearn 模型的 fit 是否调用过),而不是源码本身——先确认调用上下文,再决定是否真需要翻源码。


















