Python中setattr()与__setattr__的区别和联系是什么?

  1. setattr(obj, attr, value) just calls obj.setattr(attr, value), at least for new-style classes.

  2. setattr(instance, name, value) is syntactic sugar for instance.setattr(name, value).

  3. You would only need to call object.setattr(...) inside a class definition, and then only if directly subclassing object -- if you were subclassing something else, Spam for example, then you should either use super() to get the next item in the heirarchy, or call Spam.setattr(...) -- this way you don't risk missing behavior that super-classes have defined by skipping over them directly to object.

  4. The code is probably using object.setattr for the exact purpose of skipping the superclass's setattr

  5. 英文好的麻烦给翻译翻译上面的 4 段话的意思。感谢!


Python中setattr()与__setattr__的区别和联系是什么?

11 回复

setattr(instance, name, value)是 instance.setattr(name, value)的语法糖。


setattr() 是一个内置函数,用于动态设置对象的属性值,而 __setattr__ 是一个对象内部的方法,当你尝试给对象赋值属性时会被自动调用。

简单说,setattr(obj, 'x', 10) 是你在外面“命令”对象设置属性,而 __setattr__ 是对象内部用来“响应”这个设置操作的机制。当你写 obj.x = 10 时,Python 实际上在内部调用了 obj.__setattr__('x', 10)setattr() 函数是触发这个内部机制的一种方式。

关键区别在于控制权。直接使用 setattr() 就是普通赋值。而重写 __setattr__ 方法,你就能完全接管属性赋值的过程,比如加入验证、记录日志,或者创建“虚拟”属性。

看个例子就明白了:

class Demo:
    def __init__(self):
        # 必须直接操作__dict__来避免递归调用__setattr__
        self.__dict__['_data'] = {}

    # 重写__setattr__来接管所有属性赋值
    def __setattr__(self, name, value):
        print(f"拦截到设置属性: {name} = {value}")
        # 将所有属性存储到内部的_data字典中
        self._data[name] = value

    def __getattr__(self, name):
        # 只有当属性不存在时才调用
        if name in self._data:
            return self._data[name]
        raise AttributeError(f"属性 '{name}' 不存在")

# 使用示例
d = Demo()
setattr(d, 'score', 95)  # 输出: 拦截到设置属性: score = 95
d.grade = 'A'            # 输出: 拦截到设置属性: grade = A (效果和setattr一样)

print(d.score)  # 输出: 95
print(d.grade) # 输出: A

所以,setattr() 是工具,__setattr__ 是你可以自定义的钩子。普通使用属性时用 setattr() 或直接赋值,需要控制赋值行为时才去重写 __setattr__

一句话建议:setattr()是给属性赋值,__setattr__是定义赋值时发生什么。

setattr(instance, name, value) 是静态方法,意思为 给一个实例赋值一个属性值

instance.setattr(name, value) 是面向对象方法, 意思为一个实例设置一个属性值.

setattr 是你在外部调用的
setattr 是你在类里面实现的

意思就是我在外部用 setattr 其实是调用类里面的__setattr__方法喽?

其实我主要想知道第三段和第四段的意思?

那么这两者的功能是等价的吗?

等价的.

我理解的意思是:

在类里面可以调用 self.attr() 也可以调用 super().attr(). 这是继承的概念
调用 instance.attr()只会执行 instance 的 attr 的方法,从而隐藏了 super().

这在 OO 思想里面就是把静态方法变成实例方法, 是思想里面的差距, 和使用功能上没有差距.
另外通过 instance.attr(*) 可以达到链式表达式的效果

你可以实现 setattr 来改变属性被赋值时的行为

  1. 英文也不好,谢谢。

setattr(obj,name,value)相当于 obj.name=value
而作为函数可以更方便调用,通常用于 name 为变动值时。

setattr(self,name,value)是自定义对象方法,
用来重新定义对像的 obj.name=value 时操作
默认行为为 self.dict[name]=value,
通常用于设置检查 value 是否合法的情况。

回到顶部