使用模块__getattr__时如何回退到默认值

时间:2018-03-21 16:56:24

标签: python module attributes python-3.7

TL; DR:globals()[name]是否正确回归"默认"?

我有一大堆动态创建的类,它们是从YML文件定义的。

动态类创建是通过PyYAML yaml.safe_load_alldataclasses.make_dataclassnew 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,它似乎不是。

1 个答案:

答案 0 :(得分:5)

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

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

PEP在specification

中解释了这一点
  

如果通过正常在模块对象上找不到属性   查找(即object.__getattribute__),然后搜索__getattr__   在引发AttributeError之前模块__dict__

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