PEP 3155 – 类和函数的限定名
- 作者:
- Antoine Pitrou <solipsis at pitrou.net>
- 状态:
- 最终版
- 类型:
- 标准跟踪
- 创建日期:
- 2011年10月29日
- Python 版本:
- 3.3
- 发布历史:
- 决议:
- Python-Dev 消息
基本原理
Python 的内省功能长期以来对嵌套类的支持很差。给定一个类对象,无法知道它是在另一个类中定义的,还是在模块顶层定义的;如果是前者,也无法知道它是在哪个类中定义的。虽然使用嵌套类通常被认为是一种糟糕的风格,但它们获得二等内省支持的唯一原因是一个糟糕的双关语。
Python 3 通过取消以前称为未绑定方法的功能而雪上加霜。在 Python 2 中,给定以下定义:
class C:
def f():
pass
你可以从 C.f 对象向上追溯到它的定义类:
>>> C.f.im_class
<class '__main__.C'>
这个可能性在 Python 3 中消失了:
>>> C.f.im_class
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'im_class'
>>> dir(C.f)
['__annotations__', '__call__', '__class__', '__closure__', '__code__',
'__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__get__', '__getattribute__',
'__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__',
'__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__']
这再次限制了用户可用的内省功能。它在将软件移植到 Python 3 时可能会产生实际问题,例如 Twisted Core,其中内省方法对象的问题多次出现。它还限制了 pickle 支持 [1]。
提案
本 PEP 提议为函数和类添加一个 __qualname__ 属性。对于顶层函数和类,__qualname__ 属性等于 __name__ 属性。对于嵌套类、方法和嵌套函数,__qualname__ 属性包含从模块顶层到该对象的点分路径。函数局部命名空间在该点分路径中由一个名为 <locals> 的组件表示。
函数和类的 repr() 和 str() 已修改为使用 __qualname__ 而不是 __name__。
嵌套类的示例
>>> class C:
... def f(): pass
... class D:
... def g(): pass
...
>>> C.__qualname__
'C'
>>> C.f.__qualname__
'C.f'
>>> C.D.__qualname__
'C.D'
>>> C.D.g.__qualname__
'C.D.g'
嵌套函数的示例
>>> def f():
... def g(): pass
... return g
...
>>> f.__qualname__
'f'
>>> f().__qualname__
'f.<locals>.g'
限制
对于嵌套函数(以及在函数内部定义的类),点分路径将无法通过编程方式遍历,因为函数的命名空间无法从外部访问。但它对人类读者仍然比单纯的 __name__ 更有帮助。
与 __name__ 属性一样,__qualname__ 属性是静态计算的,它不会自动跟随重新绑定。
讨论
排除模块名
与 __name__ 一样,__qualname__ 不包括模块名。这使得它独立于模块别名和重新绑定,也允许在编译时计算它。
恢复未绑定方法
恢复未绑定方法只能解决本 PEP 解决的一小部分问题,而且代价更高(一个额外的对象类型和一个额外的间接层,而不是一个额外的属性)。
命名选择
“限定名”是该附加属性的最佳短语近似值。它不是“全名”或“完全限定名”,因为它(特意)不包括模块名。称其为“路径”可能会与文件系统路径和 __file__ 属性混淆。
最初提议的属性名称是 __qname__,但许多人(不了解 XML 规范等中此类术语的先前用法 [2])认为它晦涩难懂,不明显,因此最终选择了稍长且更明确的 __qualname__。
参考资料
版权
本文档已置于公共领域。
来源: https://github.com/python/peps/blob/main/peps/pep-3155.rst
最后修改时间: 2025-02-01 08:59:27 GMT