4

TL; DR:globals()[name]回退到“默认”的正确方法是什么?

我有大量从 YML 文件定义的动态创建的类。

动态类创建是通过PyYAMLyaml.safe_load_alldataclasses.make_dataclass3.7 中的新功能)的组合完成的。我希望这些类的规范偶尔会随着时间而改变,这就是为什么我选择 YML 作为一种易于理解的格式来描述它们。

Python 3.7 引入了新功能(参见 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]会引发 aKeyError而不是预期的AttributeError

4

1 回答 1

5

你倒过来了。模块级__getattr__函数仅作为最后手段调用。没有什么可回退的——所有其他机制都已经找不到该名称的属性。

例如,如果您的模块定义了一个全局foo变量并且有人访问了your_module.foo,那么__getattr__甚至不会被调用。

PEP 在规范中对此进行了解释:

如果通过正常查找(即object.__getattribute__)未在模块对象上找到属性,则在引发 AttributeError 之前__getattr__在模块中进行搜索。__dict__

因此,正确的“回退行为”是引发 AttributeError。

于 2018-03-21T17:28:40.173 回答