Python如何跨类调用其他类方法避免AttributeError
问题原因
报错本质是设计缺陷导致的:
- B类与C类无继承关系,B实例自身不存在
_request属性,直接调用self._request必然找不到对应方法 - C类的
_request方法强依赖调用实例持有token属性,就算强行给B实例绑定_request方法,B实例没有token属性依然会触发属性错误 - A类的
get_b_obj方法生成B实例时,没有将自身持有的请求能力、token上下文传递给B对象,导致B完全缺失发起请求的必要依赖 - 原FILE_3.py中
from FILE_2 import _C属于错误导包,FILE_2中不存在名为_C的对象
正确修复方式
通过依赖注入的方式,在创建B实例时将当前持有token、具备_request调用能力的A实例传入B,B调用请求方法时直接使用传入的A实例上下文即可,不需要修改C类的请求逻辑,也不需要给B加多余的继承关系。
各文件修改后代码如下:
FILE_1.py
from FILE_2 import C from FILE_3 import B class A(C): def __init__(self, token): self.token = token def update_something(self): self._request(body={'to_update': 'something'}) def get_b_obj(self, name): # 生成B实例时,将当前A实例自身作为参数传入 return B(name, self)
FILE_2.py
无需修改,保持原有请求封装逻辑即可:
import requests class C: def _request(self, body=None): headers = {'token': self.token} requests.get('https://example.com', headers=headers, json=body)
FILE_3.py
移除错误导包,构造方法增加A实例参数,调用请求时走传入的A实例方法:
class B: def __init__(self, name, a_client): self.name = name # 持有带token、具备请求能力的A实例引用 self.a_client = a_client def change_name(self, new_name): # 调用A实例继承自C的_request方法,方法执行时的self指向持有token的A实例,无属性错误 self.a_client._request(body={'new_name': new_name})
执行验证
原有执行逻辑无需改动,运行后可正常发起请求:
main_obj = A(token="ABC123") new_b = main_obj.get_b_obj("name") new_b.change_name("new_name")
不推荐的错误写法
- 让B类继承C类:B实例自身不持有token,继承
_request后调用时依然会因为找不到self.token报错 - 动态给B实例绑定A的
_request方法:属于隐式依赖,代码可维护性极差,后续排查问题时无法快速定位B实例的请求方法来源 - 在B实例中重新初始化一个A对象:会导致token需要重复传入,破坏原有A实例的上下文一致性,容易出现多实例token不同步的问题
内容的提问来源于stack exchange,提问作者David Lev
相关产品推荐
相关产品推荐

