[英]Are Python's dictionary view objects an exception to its assignment by value nature
根據Stack Overflow上的這個問題 ,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中還有哪些其他此類異常?
不,這也不例外。 沒有為字典視圖分配任何內容。 視圖被明確記錄為動態的 :
它們提供了字典條目的動態視圖,這意味着當字典更改時,該視圖會反映這些更改。
這是因為它們僅存儲對原始詞典的引用,並以不同於詞典API的方式為您提供直接訪問鍵,值或(key, value)
對的直接訪問權。
您可以根據需要在對象上建立自己的視圖,但是請注意,這樣的對象仍然需要引用原始對象:
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對象都生活在堆中,而名稱和屬性僅引用這些對象。 可以存在多個引用,並且每個這樣的引用都將看到對該對象所做的更改(如果允許)。 分配僅更改特定參考指向的內容。 Dict視圖在這里也不例外,它們只是繼續引用創建它們的字典。
您可能需要閱讀Python模型; 我強烈推薦Ned Batchelder撰寫的有關Python名稱和值的事實和神話 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.