TL; DR:globals()[name]
是否正确回归"默认"?
我有一大堆动态创建的类,它们是从YML文件定义的。
动态类创建是通过PyYAML yaml.safe_load_all
和dataclasses.make_dataclass
(new in 3.7)的组合完成的。我希望这些类的规范偶尔会随时间而变化,这就是为什么我选择YML作为一种易于理解的格式来描述它们。
Python 3.7引入了新功能(see PEP 562):用于管理模块属性访问的模块级__getattr__
函数(还有一个模块级__dir__
函数)。利用这个新函数可以方便地从模块名称空间导入每个动态创建的dataclass
类,如下所示:
# some_module.py
from package_name import DataClassName1, DataClassName2
......并且如此:
# package_name/__init__
from .my_dataclasses import DynamicDataClassesDict
def __getattr__(name):
try:
return DynamicDataClassesDict[name]
except KeyError:
# fall back on default module attribute lookup
在阅读PEP 562时,我不会立即明白如何回退到模块属性访问的默认功能。对于一个班级,人们只需拨打super().__getattr__(*args)
。我确实在其中一个例子中看到了这一行:
return globals()[f"_deprecated_{name}"]
这种方法似乎有效。 globals()[name]
是否正确回归"默认"?鉴于globals()[name]
将提出KeyError
而不是预期的AttributeError
,它似乎不是。
答案 0 :(得分:5)
你倒退了。模块级__getattr__
函数仅作为最后手段调用。没有什么可以回溯 - 所有其他机制都已经找不到该名称的属性。
例如,如果您的模块定义了全局foo
变量并且某人访问了your_module.foo
,那么__getattr__
甚至不会被调用。
PEP在specification:
中解释了这一点如果通过正常在模块对象上找不到属性 查找(即
object.__getattribute__
),然后搜索__getattr__
在引发AttributeError之前模块__dict__
。
因此,正确的"回退行为"是引发AttributeError。