Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python2.7上使用AttrDict时出现奇怪的错误_Python_Python 2.7 - Fatal编程技术网

在Python2.7上使用AttrDict时出现奇怪的错误

在Python2.7上使用AttrDict时出现奇怪的错误,python,python-2.7,Python,Python 2.7,在Python2.7上使用AttrDict2.0时,我遇到了一个奇怪的重复错误。奇怪的是,传递赋值似乎会中断,但只有在使用AttrDict时才会中断 发生的事情是,如果一个对象不存在,我想在该对象上实例化一个新列表,然后向其追加数据 如果我使用AttrDict,列表会以某种方式转换为元组,我会得到一个异常 from attrdict import AttrDict class Test(object): pass try: for cls_ in [Test,AttrDic

在Python2.7上使用AttrDict2.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]
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
自动递归的一部分。与自述文件相比,内联
帮助
(您可以在源代码中找到)中更好地解释了这一点:

如果作为属性访问的值是序列类型(而不是字符串/字节),它将转换为_Sequence_类型,其中的任何映射都将转换为Attrs

换句话说,为了在执行属性访问时将
AttrDict
中的任何
dict
或其他映射递归地自动转换为
AttrDict
值,它还将所有序列转换为(默认情况下)
元组。这有点奇怪,但似乎是故意的,并且有一些记录在案的行为,而不是bug

>>> 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
的类型)


好的,但即使这指向AttrDict端的一些奇怪行为,传递赋值怎么也不赋值元组呢

因为这不是链式分配的工作方式。有点过于简单化:

target1 = target2 = value
…不等同于此:

target2 = value
target1 = target2
target2 = value
target1 = value
……但对此:

target2 = value
target1 = target2
target2 = value
target1 = value
理解这一点的最佳方式是:目标不是表达式,因此没有值。当然,通常完全相同的标记序列作为语法中其他地方的表达式是有效的,但该标记序列在赋值语句中的任何地方都不会作为表达式进行计算,否则,如果
d['spam']='egs'
不存在,则像
d['spam']
这样的简单操作将不得不引发异常

而且,
a.li=[]
实际上并不在任何地方分配
元组([])
;它实际上在内部存储
[]
,并在稍后尝试访问
a.li
时执行
元组(…)
。在没有阅读源代码的情况下,你不能确切地说出这一点,但是当你认为<>代码> ['Li ] 给你<代码> []/Cord>而不是<代码>()<代码>时,它几乎必须是真的。事实上:

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

您应该能够在不使用所有其他东西的情况下对其进行测试:如果只执行
a=AttrDict(),会发生什么;a、 li=[];打印(a.li)
?是
[]
还是
()
?如果是后者,那么你问题中的所有其他内容都是无关的。我添加chk只是为了尝试调试,它以前是坏的。测试类是为了确保我没有搞乱属性初始化,它似乎指出了AttrDict的一个问题。但是,是的,我会添加您的建议。这似乎是
AttrDict
的预期行为,即使自述文件中没有对此进行很好的解释。因此,传递性作业中的每个目标都会得到列表。AttrDict将其转换为元组,但这是它的业务,在我的示例中不影响对
chk
/
b
的赋值?有道理。@JLPeyret完全正确。事实上,如果您通读源代码,
AttrDict
现在甚至不会将其转换为元组,但只有在以后,当您通过
a.li
访问它时才会将其转换为元组。这就是为什么
a['li']
仍然可以工作的原因。