1. 基本用法
默认情况下,Python 自动处理属性赋值。但你可以重写 setattr 来拦截赋值。
class A:def __setattr__(self, name, value):super().__setattr__(name, value)
2. 必须使用 super().setattr 才能真正赋值
错误写法(会无限递归):
def __setattr__(self, name, value):self.x = value # ❌ 再次触发 __setattr__,无限递归
正确写法:
super().__setattr__(name, value)
3. 常见用途
3.1 属性验证
class Person:def __setattr__(self, name, value):if name == "age" and value < 0:raise ValueError("age cannot be negative")super().__setattr__(name, value)
3.2 自动类型转换或格式化
class Config:def __setattr__(self, name, value):if name == "path":value = value.replace("\\", "/")super().__setattr__(name, value)
3.3 禁止动态新增属性
class Locked:allowed = {"x", "y"}def __setattr__(self, name, value):if name not in self.allowed:raise AttributeError(f"Cannot add new attribute: {name}")super().__setattr__(name, value)
3.4 记录属性赋值(日志用途)
class Monitor:def __setattr__(self, name, value):super().__setattr__(name, value)
4. 与 getattr / getattribute 的关系
方法 触发时机 说明
setattr 属性赋值时 控制 obj.x = v
getattr 找不到属性时 后备属性查找
getattribute 所有属性访问时 最底层拦截器
delattr 删除属性时 控制 del obj.x
setattr 只负责 设置,而另两个负责 获取。
5. 常见错误(必须避免)
5.1 在内部使用 self.x = ...(导致递归)
def __setattr__(self, name, value):self.x = value # ❌ 无限递归
5.2 忘记写
super().__setattr__
导致属性根本不会被保存。
6.保存需要插入数据库的列(用这个可以避免影响这些列)
#sampleself.name = 'a'self.attrs = copy.copy(obj._attrs)self.gui_name = 'a'
通过控制self.attrs = copy.copy(obj._attrs)的位置分割需要插数据库和不需要插数据库的属性,obj._attrs在__setattr__方法中增加需要插入数据库的列名,后续修改属性时使用super().__setattr__确保attrs不受影响。