为什么在Python中使用__setattr__?

26 投票
7 回答
38128 浏览
提问于 2025-04-16 16:14

我不明白为什么要用 __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 个回答

8

我可以想象一个应用场景,比如你可以重写 __setattr____getattr__ 这两个方法,让你可以像操作对象一样访问一些不在内存中的数据结构。举个例子,你可以创建一个对象,当你写 foo.CustomerName = "John" 时,它会把数据库中与 foo 相关的那一行的 CustomerName 列更新为 "John"。也就是说,foo.__setattr__ 会利用属性名和属性值来构建一个命令,去更新硬盘上的数据库。我不太想写这样的东西,但确实是可以做到的。

18

__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)
34

你不需要自己去调用这个。就是这么简单。如果你需要用字符串来表示某个名字,因为你事先不知道这个名字是什么(在99%的情况下,这个想法非常糟糕,通常用字典或列表会更好、更合理),你可以使用内置的 setattr 函数。

不过,当你写 a.x = ... 的时候,实际上是调用了 a.__setattr__('x', ...)(这可能是个过于简单化的说法)。而且有些对象会重写这个方法,以实现一些特殊的功能,比如模拟不可变性。可以查看“特殊方法”的文档。

撰写回答