簡體   English   中英

Python的字典視圖對象是否是其按值性質分配的例外

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM