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

Python 2.7中使用AttrDict 2.0出现异常问题咨询

Python 2.7 + AttrDict 2.0: 列表被莫名转为元组导致赋值异常

我之前也碰到过类似的坑!先把你的代码补全成可复现的完整版本,方便大家理解问题场景:

from attrdict import AttrDict

class Test(object):
    pass

try:
    for cls_ in [Test, AttrDict]:
        foo = cls_()
        print("\ntesting with class {}...".format(cls_.__name__))
        # 核心逻辑:尝试给列表追加元素,不存在则默认初始化
        foo.my_list += [1]
        print("Final value: {}, type: {}".format(foo.my_list, type(foo.my_list)))
        # 后续追加操作会触发异常
        foo.my_list.append(2)
except Exception as e:
    print("Error occurred: {}".format(e))

运行这段代码后,Test类会直接抛出AttributeError(因为my_list未定义),但AttrDict会先把my_list悄悄转成元组,后续执行append时才抛出'tuple' object has no attribute 'append'的异常。

问题根源

AttrDict 2.0在Python 2.7中的__getattr__方法有个特殊的“魔法”处理:当你访问一个不存在的属性(键)时,它不会像普通类那样抛出AttributeError,而是返回一个空元组。

这就导致foo.my_list += [1]的实际执行逻辑变成了:

foo.my_list = getattr(foo, 'my_list', ()) + [1]

空元组和列表相加的结果是元组(1,),这个元组被赋值给foo.my_list,后续的append操作自然会因为元组不可变而报错。

解决方案

针对这个问题,有几种稳妥的解决方式:

  1. 显式检查并初始化列表
    不要依赖+=的隐式行为,先明确判断属性是否存在,不存在就初始化为空列表:

    for cls_ in [Test, AttrDict]:
        foo = cls_()
        print("\ntesting with class {}...".format(cls_.__name__))
        if not hasattr(foo, 'my_list'):
            foo.my_list = []
        foo.my_list.append(1)
        foo.my_list.append(2)
        print("Final value: {}, type: {}".format(foo.my_list, type(foo.my_list)))
    
  2. 用getattr显式指定列表默认值
    如果喜欢简洁写法,可以通过getattr主动传入空列表作为默认值,避免AttrDict返回空元组:

    for cls_ in [Test, AttrDict]:
        foo = cls_()
        print("\ntesting with class {}...".format(cls_.__name__))
        foo.my_list = getattr(foo, 'my_list', [])
        foo.my_list.append(1)
        foo.my_list.append(2)
        print("Final value: {}, type: {}".format(foo.my_list, type(foo.my_list)))
    
  3. 升级AttrDict版本(若环境允许)
    这个隐性bug在AttrDict 2.2.0及以后的版本中已经被修复,新版本访问不存在的属性会直接抛出AttributeError,和普通类行为一致。不过要注意确认新版本是否兼容Python 2.7。

额外提醒

在Python 2.7中使用AttrDict时,尽量避开它对不存在属性的隐式返回逻辑,这种“魔法”行为很容易引发难以排查的隐性问题,显式初始化是最稳妥的选择。

内容的提问来源于stack exchange,提问作者JL Peyret

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:11:58