为什么在Python中使用__setattr__?
我不明白为什么要用 __setattr__
,而不是简单地像 x.a=1
这样直接赋值。
我明白这个例子:
class Rectangle:
def __init__(self):
self.width = 0
self.height = 0
x=Rectangle()
x.width=20
x.__setattr__('height',30)
setattr(x,'width',99)
但我不明白为什么要用字符串('height')来写代码。
你能给我解释一下 __setattr__
的好处吗?
7 个回答
我可以想象一个应用场景,比如你可以重写 __setattr__
和 __getattr__
这两个方法,让你可以像操作对象一样访问一些不在内存中的数据结构。举个例子,你可以创建一个对象,当你写 foo.CustomerName = "John"
时,它会把数据库中与 foo
相关的那一行的 CustomerName
列更新为 "John"
。也就是说,foo.__setattr__
会利用属性名和属性值来构建一个命令,去更新硬盘上的数据库。我不太想写这样的东西,但确实是可以做到的。
__setattr__
是一个类的方法,它是由内置的 setattr
方法调用的。也就是说,如果在某个类中定义了 __setattr__
,那么这个方法就会被使用。大多数情况下,你并不需要自己写 __setattr__
的版本,所以我猜你想知道 setattr
方法有什么用。
假设你有一个变量,它的值是你想要设置的属性的名字,而不是直接知道这个名字:
class A(object):
def doSth(self, name, val):
setattr(self, name, val)
这样就无法通过 self.name = val
来实现。
另外,setattr
还有一个常见的用法,就是和关键字参数一起使用:
class A(object):
def __init__(self, *args, **kwargs):
for k,v in kwargs.items():
setattr(self, k, v)
你不需要自己去调用这个。就是这么简单。如果你需要用字符串来表示某个名字,因为你事先不知道这个名字是什么(在99%的情况下,这个想法非常糟糕,通常用字典或列表会更好、更合理),你可以使用内置的 setattr
函数。
不过,当你写 a.x = ...
的时候,实际上是调用了 a.__setattr__('x', ...)
(这可能是个过于简单化的说法)。而且有些对象会重写这个方法,以实现一些特殊的功能,比如模拟不可变性。可以查看“特殊方法”的文档。