gpt4 book ai didi

python - 在 Python 2.7 上使用 AttrDict 时出现奇怪的错误

转载 作者:行者123 更新时间:2023-12-01 01:56:05 27 4
gpt4 key购买 nike

我在 Python 2.7 上使用 AttrDict 2.0 时遇到奇怪的重复错误。奇怪的是,传递赋值似乎会被破坏,但只有在使用 AttrDict 时才会被破坏。

发生的情况是,我想在对象上实例化一个新列表(如果它不存在),然后向其附加数据。

如果我使用 AttrDict,列表会以某种方式转换为元组,并且会出现异常。

from attrdict import AttrDict

class Test(object):
pass

try:

for cls_ in [Test,AttrDict]:
foo = cls_()
print ("\ntesting with class %s" % (cls_))

#this
chk = foo.li = getattr(foo, "li", None) or []
print(" type(chk):%s, id(chk):%s" % (type(chk),id(chk)))
print(" type(foo.li):%s, id(foo.li):%s" % (type(foo.li),id(foo.li)))
foo.li.append(3)
print (" success appending with class %s: foo.li:%s" % (cls_, foo.li))

except (Exception,) as e:
# pdb.set_trace()
raise

现在检查一下使用 Test 类与使用 AttrDict 时的输出。

testing with class <class '__main__.Test'>
type(chk):<type 'list'>, id(chk):4465207704
type(foo.li):<type 'list'>, id(foo.li):4465207704
success appending with class <class '__main__.Test'>: foo.li:[3]

使用自定义 Test 类,正如预期的那样,chkfoo.li 都是列表,并且具有相同的 id。追加作品。

使用 AttrDict 查看传递,id 不匹配,并且 foo.li 是元组而不是列表。

testing with class <class 'attrdict.dictionary.AttrDict'>
type(chk):<type 'list'>, id(chk):4465207848
type(foo.li):<type 'tuple'>, id(foo.li):4464595080
Traceback (most recent call last):
File "test_attrdict2.py", line 25, in <module>
test()
File "test_attrdict2.py", line 18, in test
foo.li.append(3)
AttributeError: 'tuple' object has no attribute 'append'

attrdict 赋值实际上是否返回某种属性/访问器对象,该对象在您第二次访问它时会发生更改?

采纳@abartnet的建议:

from attrdict import AttrDict
a = AttrDict()
a.li = []
print(a.li)

输出:()

好的,但即使这表明 AttrDict 端有一些奇怪的行为,传递赋值怎么也不会分配元组呢?

重新设计:

from attrdict import AttrDict
a = AttrDict()
b = a.li = []
print("a.li:", a.li)
print("b:",b)

输出:

('a.li:', ())
('b:', [])

最佳答案

这是 AttrDict 自动递归的一部分。内联 help(您可以在源代码中找到 here)比自述文件中解释得更好:

If a values which is accessed as an attribute is a Sequence-type (and is not a string/bytes), it will be converted to a _sequence_type with any mappings within it converted to Attrs.

换句话说,为了在进行属性访问时将任何 dictAttrDict 内的其他映射递归地自动转换为 AttrDict 值,它还会将所有序列转换为(默认情况下) tuple 。这有点奇怪,但似乎是有意且有记录的行为,而不是错误。

>>> a = AttrDict()
>>> a._sequence_type
tuple
>>> a.li = []
>>> a.li
()
<小时/>

更灵活的 AttrMap 类型允许您指定序列类型,并记录您可以通过传递 None 来禁用此递归重新映射内容:

>>> a = AttrMap(sequence_type=None)
>>> a.li = []
>>> a.li
[]

但是当然 AttrMap 不是 dict (尽管它是 collections.abc.MutableMapping ,更一般地说,它鸭子类型为 dict 类似类型)。

<小时/>

OK, but even if that points to some weird behavior on AttrDict's end, how is it the transitive assignment does not assign the tuple as well?

因为这不是链式赋值的工作原理。有点过于简单化了:

target1 = target2 = value

...不等于:

target2 = value
target1 = target2

…但是对此:

target2 = value
target1 = value

理解其原因的最佳方法是:目标不是表达式,因此没有值。当然,通常完全相同的标记序列作为语法中其他地方的表达式有效,但是该标记序列永远不会在赋值语句中的任何位置被评估为表达式 - 否则,像 d['spam'] = 'eggs' 这样的简单的东西如果 d['spam'] 不存在,则必须引发异常。

此外,a.li = [] 实际上并没有在任何地方分配 tuple([]);它实际上在内部存储 [] ,并在稍后当您尝试访问 tuple(…) 时执行 a.li 。如果不阅读源代码,你无法确定这一点,但是当你考虑到 a['li'] 给你的是 [] 而不是 () 时,它几乎一定是真的。事实上:

>>> li = []
>>> a.li = li
>>> a['li'] is li
True

关于python - 在 Python 2.7 上使用 AttrDict 时出现奇怪的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50181509/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com