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。
请您参考如下方法:
你把它倒过来了。模块级 __getattr__ 函数仅作为最后手段调用。没有什么可以回退 - 所有其他机制都已经无法找到该名称的属性。
例如,如果你的模块定义了一个全局的foo变量并且有人访问了your_module.foo,那么__getattr__甚至不会被调用.
PEP 在 specification 中解释了这一点:
If an attribute is not found on a module object through the normal lookup (i.e.
object.__getattribute__), then__getattr__is searched in the module__dict__before raising an AttributeError.
因此,正确的“回退行为”是引发 AttributeError。
