2017-06-16 78 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