PEP 3155 – 类和函数的限定名称
- 作者:
- Antoine Pitrou <solipsis at pitrou.net>
- 状态:
- 最终
- 类型:
- 标准跟踪
- 创建:
- 2011年10月29日
- Python版本:
- 3.3
- 历史记录:
- 决议:
- Python-Dev消息
基本原理
Python的内省机制长期以来对嵌套类支持不佳。给定一个类对象,无法知道它是在另一个类内部定义的还是在模块顶层定义的;如果是前者,也无法知道它是在哪个类中定义的。虽然嵌套类的使用通常被认为是不好的风格,但它们拥有二等内省支持的唯一原因是一个糟糕的双关语。
Python 3 通过放弃以前称为未绑定方法的内容,雪上加霜。
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,其中多次出现内省方法对象的问题。它还限制了 pickling 支持 [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