Python中实现类间属性传递与访问,解决__init__参数错误
解决User与Client类属性传递的报错问题
嘿,我来帮你搞定这个问题!你想要实现的效果是:创建User实例后,既能直接通过user.x、user.y访问自身属性,又能通过user.client.x这种方式让Client对象代理访问User的部分属性,但现在遇到了TypeError: __init__() takes 1 positional argument but 2 were given的报错,这问题很好解决,我给你一步步拆解。
首先先看你写的简化后代码:
class User(object): def __init__(self, x, y): self.x = x self.y = y self.client = Client(self) # 这里给Client传了当前User实例 @property def z(self): return "test" class Client(object): def __init__(...): # 你这里没定义接收参数的位置 pass
错误原因分析
你在User的__init__里调用了Client(self),相当于给Client的构造方法传了一个额外的参数(当前的User实例),但Client类的__init__方法只默认接收self这一个参数,Python就会报错说你传了2个参数(自动传入的self + 你手动传的User实例),但构造方法只接受1个。
解决方案
我们只需要给Client的__init__添加一个参数来接收User实例,然后通过属性代理或者动态属性查找来实现需求,有两种常用方式:
方式一:手动写@property代理指定属性
这种方式适合你明确知道要代理哪些属性的场景,可读性强:
class User(object): def __init__(self, x, y): self.x = x self.y = y # 把当前User实例传给Client的构造方法 self.client = Client(self) @property def z(self): return "test" class Client(object): def __init__(self, user): # 保存User实例的引用,后续用来访问属性 self._user = user # 代理User的x属性 @property def x(self): return self._user.x # 代理User的y属性 @property def y(self): return self._user.y # 也可以代理User的z这个@property属性 @property def z(self): return self._user.z
方式二:用__getattr__动态代理属性
如果需要代理的属性比较多,不想一个个写@property,可以用__getattr__方法,它会在访问实例不存在的属性时自动触发,我们可以在这里做动态转发:
class User(object): def __init__(self, x, y): self.x = x self.y = y self.client = Client(self) @property def z(self): return "test" class Client(object): def __init__(self, user): self._user = user # 定义允许代理的属性列表,避免无限制访问User的所有属性 self._allowed_attrs = {'x', 'y', 'z'} def __getattr__(self, name): if name in self._allowed_attrs: # 去User实例中获取对应的属性 return getattr(self._user, name) # 如果是不允许的属性,抛出标准的AttributeError raise AttributeError(f"'Client' object has no attribute '{name}'")
测试验证
不管用哪种方式,你都能实现想要的访问效果:
user = User(x=1, y=2) print(user.x) # 输出: 1 print(user.y) # 输出: 2 print(user.z) # 输出: test print(user.client.x) # 输出: 1 print(user.client.y) # 输出: 2 print(user.client.z) # 输出: test
内容的提问来源于stack exchange,提问作者MarkK
相关产品推荐
相关产品推荐

