我有些偶然地发现,您可以使用设置对象的“非法”属性setattr。非法是指__getattr__具有传统.操作员引用的接口无法检索的名称属性。它们只能通过getattr方法检索。
在我看来,这似乎非常令人惊讶,我想知道是否有这个原因,或者只是被忽略了,等等。由于存在用于检索属性的运算符和setattribute接口的标准实现,所以我希望它仅允许实际上可以正常检索的属性名称。而且,如果出于某些奇怪的原因想要具有无效名称的属性,则必须为它们实现自己的接口。
我一个人会为这种行为感到惊讶吗?
class Foo:
"stores attrs"
foo = Foo()
setattr(foo, "bar.baz", "this can't be reached")
dir(foo)
Run Code Online (Sandbox Code Playgroud)
这将返回既奇怪又有点误导的东西:
[...'__weakref__', 'bar.baz']
而且,如果我想以“标准”方式访问foo.bar.baz,则不能。无法检索它是很有意义的,但是设置它的能力令人惊讶。
foo.bar.baz
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'bar'
Run Code Online (Sandbox Code Playgroud)
是否只是假设,如果必须使用setattr来设置变量,您将通过引用它getattr?因为在运行时,这可能并不总是正确的,尤其是使用Python的交互式解释器,反射等时。默认情况下允许这样做仍然很奇怪。
编辑:我希望看到的作为setattr的默认实现的一个(非常粗糙的)示例:
import re
class Safe:
"stores attrs"
def __setattr__(self, attr, value):
if not re.match(r"^\w[\w\d\-]+$", attr):
raise AttributeError("Invalid characters in attribute name")
else:
super().__setattr__(attr, …Run Code Online (Sandbox Code Playgroud)