You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python使用__getattr__与__setattr__实现子变量双访问方式及报错解决

问题根因

  1. 递归触发原因:
    你自定义的__setattr__拦截了所有实例属性赋值操作,初始化self.children = {}时,属性名children没有被你的放行规则匹配到,不会被真正赋值到实例上。后续访问self.children时,因为实例本身没有这个属性,会触发__getattr__,而__getattr__中又返回self.children,再次触发__getattr__,形成死循环最终抛出递归溢出错误。
  2. __setattr__逻辑错误:
    你当前写的super().__setattr__('children[{}]'.format(prop), val)是给实例新增了一个名为children[Alfa]的字符串属性,完全没有操作children字典内的元素,无法实现预期的赋值逻辑。
  3. __getattr__冗余逻辑:
    __getattr__中判断name == 'children'的分支完全没必要,只要children被正确赋值到实例上,访问该属性不会触发__getattr__。

修正方案

完整可运行代码:

#!/usr/bin/env python3.6

class Child(object):
  def __init__(self, name:str, value = 0):
    self.name = name
    self.value = value
  def __repr__(self):
    return '  child "{}" has value {}\n'.format(self.name, self.value)

class Parent(object):
  def __init__(self, name:str):
    self.name = name
    self.children = {}

  def __repr__(self):
    s = 'Parent "{}":\n'.format(self.name)
    for k, v in self.children.items():
      s += v.__repr__()
    return s

  def __getattr__(self, name:str):
    # 只有实例不存在的属性才会走到这里,无需额外判断children
    if name in self.children:
      return self.children[name].value
    raise AttributeError(f"'Parent' object has no attribute '{name}'")

  def __setattr__(self, prop, val):
    # 放行实例原生属性name和children,直接赋值到实例
    if prop in ('name', 'children'):
      super().__setattr__(prop, val)
    else:
      # 子项已存在则修改对应value
      if prop in self.children:
        self.children[prop].value = val
      # 可选逻辑:子项不存在则自动新增Child实例到children字典,不需要可删除改为抛异常
      else:
        self.children[prop] = Child(prop, val)


p = Parent('Tango')
p.children['Alfa'] = Child('Alfa', 55)
p.children['Bravo'] = Child('Bravo', 66)
print(p)
print(p.children['Alfa'])  # 输出 child "Alfa" has value 55
print(p.Alfa)              # 输出 55

print('-----')
p.Alfa = 99
print(p.Alfa)  # 输出 99
print('-----')

print(p.children['Alfa'])  # 输出 child "Alfa" has value 99
print(p)                   # 输出的Alfa value已更新为99

效果说明

修正后p.Alfa = 99会直接修改children['Alfa']的value属性,完全符合需求。可选的自动新增子项逻辑可以根据实际业务需求调整。

内容的提问来源于stack exchange,提问作者Lance E.T. Compte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 10:39:04