我有点意外地发现,您可以使用setattr
. 非法,我的意思是属性名称无法使用__getattr__
具有传统.
运算符引用的接口检索。它们只能通过该getattr
方法检索。
对我来说,这似乎相当令人惊讶,我想知道这是否有原因,或者是否只是被忽略了等等。由于存在用于检索属性的运算符和setattribute
接口的标准实现,我希望它只允许实际上可以正常检索的属性名称。而且,如果您有一些奇怪的理由想要具有无效名称的属性,则必须为它们实现自己的接口。
只有我对这种行为感到惊讶吗?
class Foo:
"stores attrs"
foo = Foo()
setattr(foo, "bar.baz", "this can't be reached")
dir(foo)
这会返回一些既奇怪又有点误导的东西:
[...'__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'
是否只是假设,如果您必须使用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, value)
这将不允许我在属性名称中使用无效字符。显然,super()
不能在基 Object 类上使用,但这只是一个示例。