何时需要为Python类定义__getattr__()和__setattr__()方法?
Python中委托模式下
__getattr__与__setattr__的使用指南 官方Python编程FAQ提到,在实现面向对象的**委托(delegation)**概念时,部分场景需要定义object.__getattr__(self, name)和object.__setattr__(self, name, value)方法,但未给出明确的通用判断标准。以下是结合示例和概念的具体说明:
FAQ示例解析
官方给出的示例用于实现一个类,它表现得像文件对象,但会把所有写入的内容转为大写:
class UpperOut: def __init__(self, outfile): self._outfile = outfile def write(self, s): self._outfile.write(s.upper()) def __getattr__(self, name): return getattr(self._outfile, name)
- 这里
__getattr__的作用是:当访问UpperOut实例中不存在的属性/方法时,会自动委托给内部的_outfile对象处理。比如调用upper_out.close()时,因为UpperOut没有定义close方法,就会通过__getattr__调用_outfile.close()。 - FAQ特别提示:如果需要支持设置或修改属性,定义
__setattr__时要格外谨慎——如果直接在__setattr__里调用setattr(self, name, value)会触发无限递归,通常需要先处理自身属性,再委托给内部对象。
为什么不用继承?
有人疑惑这个示例为何不采用继承实现,原因在于这是为了演示无继承的纯委托模式:
- Python 3中
file并非独立类型,无法直接继承; - 更关键的是,普通继承会自动继承父类的所有属性和方法,不需要显式实现委托逻辑。而纯委托模式下,我们可以精确控制哪些行为自己处理,哪些委托给内部对象(比如示例中只重写了
write方法,其他方法全委托)。
委托与继承的核心区别
根据维基百科的定义:
在面向对象编程中,委托指在一个对象的上下文中计算另一个对象的成员,可显式或隐式实现;隐式委托是原型编程中行为复用的基础,对应类编程中的继承。
狭义上:
- 继承是类与类之间的关系(一个类继承自另一个类),属于类编程的复用方式;
- 委托是对象与对象之间的关系(一个对象将请求委托给另一个对象处理),是原型编程的核心复用技术。
需要注意的是,委托在Python中并不属于常用的编程模式。
内容的提问来源于stack exchange,提问作者Lover of Structure
相关产品推荐
相关产品推荐

