我在
模块上实现了自定义
__getattr__
,它检索值并使用setattr
缓存它。这是简化版本:
# mymodule.py
import sys
__this = sys.modules[__name__]
def __getattr__(name: str):
print(f"Generating {name}")
value = "some value"
setattr(__this, name, value)
return value
这很好用:
>>> import mymodule
>>> mymodule.foo
Generating foo
'some value'
>>> mymodule.bar
Generating bar
'some value'
>>> mymodule.bar
'some value'
注意如何仅在模块上尚不存在的属性上调用
__getattr__
。我如何识别这些属性? Python 显然知道它们,但我无法获取这些信息。
hasattr
不起作用,因为在幕后它调用了getattr
,它调用了我的函数:
>>> hasattr(mymodule, "foo")
True
>>> hasattr(mymodule, "something")
Generating something
True
"foo" in dir(mymodule)
可以工作,但需要使用 dir()
枚举 all属性来测试单个属性。人们可以使用
del mymodule.foo
删除属性,因此使用全局 __getattr__
在 set
中跟踪它们不起作用(并且尚不支持自定义 __delattr__
)。
如何在不调用 mymodule
的情况下测试“某物”是否是
mymodule.__getattr__
的属性?
__dict__
。
>>> mymodule.__dict__
{...}
>>> "foo" in mymodule.__dict__
True
>>> "something" in mymodule.__dict__
False
请记住,__dict__
还包含某些您未明确定义的内容,例如
__name__
和
__doc__
(存在于所有模块上)。尽管尝试访问这些无论如何都不会调用您的
__getattr__
,所以它与您正在寻找的行为一致。