2017-06-16 40 views
-1

根据this question on Stack Overflow,Python中的赋值始终是值,因此您无法更改原始源。例如(来自同样的问题),Python的字典视图对象是否按值赋予其赋值异常

locs = [ [1], [2] ] 
for loc in locs: 
    loc = [] 

print locs 
# prints => [ [1], [2] ] 

然而,字典视图对象示出了相反的行为

bike = {"Manufacturer":"Honda","Model":"CBR","cc":250,"price":70,"mileage":74} 

keys = bike.keys() 
print(keys) 

bike["tyres"] = 2 
print(keys) 

这是输出:

dict_keys(['mileage', 'price', 'Model', 'Manufacturer', 'cc']) 
dict_keys(['cc', 'Manufacturer', 'tyres', 'mileage', 'Model', 'price']) 

可以它们被视为例外以赋值性质?如果是的话,那么Python3中的其他例外情况如何?

回答

2

不,这不是例外。没有任何内容被分配到字典视图。视图明确documented as being dynamic

它们提供了对字典条目的动态视图,这意味着当字典更改时,视图反映了这些更改。

这是因为他们只保存到原来的参考字典,并为您提供直接访问刚刚的钥匙,或者只是值,或者(key, value)双在从字典API不同的方式。

你可以建立自己的看法到物体上,如果你想要的,但要注意,这样的对象仍需要原始对象(或多个)参考:

from collections.abc import Sequence 

class ListReversedView(Sequence): 
    def __init__(self, lst): 
     self._lst = lst 
    def __getitem__(self, idx): 
     if idx < 0: 
      new = (-idx) - 1 
     else: 
      new = len(self) - idx - 1 
      if new < 0: 
       raise IndexError(new) 
     return self._lst[new] 
    def __len__(self): 
     return len(self._lst) 
    def __repr__(self): 
     return f"[{', '.join(map(repr, self))}]" 

上面的例子给你一个不同的看法列表内容;这个对象提供的'视图'反映了列表的变化。 Python的分配模型没有什么特别的需要去做;任务仍然对象只是引用,并在此视图对象的属性_lst也不例外:

>>> foo = ['spam', 'ham', 'eggs'] 
>>> view = ListReversedView(foo) 
>>> view 
['eggs', 'ham', 'spam'] 
>>> foo[-1] = 'bacon' 
>>> view 
['bacon', 'ham', 'spam'] 

盘旋回你的列表循环;你仍然可以分配给列表对象本身;重新绑定名称可能无法正常工作,但重新绑定指数的作品就好了:

for index in range(len(locs)): 
    locs[index] = [] 

总之,Python对象都生活在一个堆,以及名称和属性只是引用这些对象。可以存在多个引用,每个这样的引用都会看到对该对象所做的更改(如果允许的话)。分配仅更改特定参考指向的内容。字典视图在这里也不例外,他们只是继续引用它们创建的字典。

您可能想要阅读Python模型;我强烈推荐Facts and myths about Python names and values article by Ned Batchelder