簡體   English   中英

在python中,以下AutoVivification類如何工作?

[英]In python, how does the following AutoVivification class work?

在尋找使用嵌套字典的方法時,我發現nosklo發布了以下代碼,我想解釋一下。

class AutoVivification(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value

測試:

a = AutoVivification()

a[1][2][3] = 4
a[1][3][3] = 5
a[1][2]['test'] = 6

print a

輸出:

{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}

我是一個非常新手的程序員。 我在自己的時間里學到了大部分我所知道的知識,我在高中時只接受過Turbo Pascal的正式訓練。 我理解並能夠以簡單的方式使用類,例如使用__init__ ,類方法,並使用foo.man = 'choo'在類的實例中存儲數據。

我不知道方括號系列是如何正確地通過類來定向的(我假設它們以某種方式調用__getitem__ )並且不理解它們如何被如此簡潔地處理,而不必單獨調用該方法三次。

我的印象是,類聲明中的(dict)將由__init__處理。

我曾經try: except:之前,盡管如此,以非常簡單的方式。 它看起來像try ,當它運行時,正在調用一系列函數__getitem__ 我知道如果當前級別的字典存在,則try將通過並轉到下一個字典。 我收集的except ,當有一個KeyError時運行,但我還沒有看到過像以前那樣的self使用。 當我認為self是一個class AutoVivification一個實例時, Self被視為字典......它是兩個嗎? 我從來沒有像這樣連續兩次分配foo = man = choo但懷疑value指向self[item]self[item]指向type(self)的結果。 但是type(self)會返回類似這樣的內容: <class '__main__.AutoVivification'>不是嗎? 我不知道最后有什么額外的圓括號。 因為我不知道如何調用函數,我不明白返回value位置。

抱歉有這些問題! 有這么多,我不明白,我不知道在哪里查閱,只需閱讀文檔幾個小時,我保留很少。 這段代碼看起來像是為了我的目的但我想在使用之前理解它。

如果你想知道我在我的程序中嘗試使用嵌套字典做什么:我試圖以天文數字的形式保存地圖數據。 雖然我無法創建嵌套4次的10 ^ 6項的字典/列表(也就是10 ^ 24項!),但空間大部分都是空的,所以我可以完全保留空值,只有在那里有東西時才分配。 困擾我的是處理字典的有效方式。

逐行:

class AutoVivification(dict):

我們創建了一個dict的子類,所以AutoVivification是一種dict ,有一些局部的變化。

def __getitem__(self, item):

__getitem()__被稱為每當有人試圖通過對實例訪問項目[...]索引查找。 因此,每當有人對object[somekey]type(object).__getitem__(object, somekey)被調用。

我們暫時跳過try ,下一行是:

 return dict.__getitem__(self, item)

這將調用未綁定的方法__getitem__() ,並將自己的實例與密鑰一起傳遞給它。 換句話說,我們稱之為父類dict定義的原始 __getitem__

現在,我們都知道如果字典中沒有item密鑰會發生什么,會引發KeyError 這是try: , except KeyError組合except KeyError

    try:
        return dict.__getitem__(self, item)
    except KeyError:
        value = self[item] = type(self)()
        return value

所以,如果目前的情況下(這是子類型的dict )沒有給定的鍵,它會捕捉KeyError例外原來dict.__getitem__()方法拋出,而是我們創造了新的價值,商店在self[item]並返回該值。

現在,請記住selfdict的(子類),所以它是一個字典。 因此,它可以分配新的值(它將使用__setitem__鈎子 ,並且在這種情況下,它會創建一個與self相同類型的實例)。 這是另一個dict子類。

那么當我們稱a[1][2][3] = 4什么呢? Python經歷了這一步:

  1. a[1]導致type(a).__getitem__(a, 1) 自定義__getitem__的方法AutoVivification捕獲KeyError ,創建的實例AutoVivification ,賣場,根據鍵1和返回。

  2. a[1]返回一個空的AutoVivification實例。 在該對象上調用下一個項[2] ,我們重復步驟1中發生的事情; 有一個KeyError ,的新實例AutoVivification創建,下保存2鍵,新的實例返回給調用者。

  3. a[1][2]返回一個空的AutoVivification實例。 在該對象上調用下一個訪問項[3] ,我們重復步驟1(和步驟2)中發生的事情。 有一個KeyError ,的新實例AutoVivification創建,在存儲的3鍵,而新的實例返回給調用者。

  4. a[1][2][3]返回一個空的AutoVivification實例。 現在我們在該實例中存儲一個新值, 4

一旦你轉到下一行代碼, a[1][3][3] = 5 ,頂級AutoVivification實例已經有一個1鍵, return dict.__getitem__(self, item)行將返回相應的值,恰好是上面第一步中創建的AutoVivification實例。

從那里, [3]項訪問調用將再次創建一個新的AutoVivification實例(因為a[1]處的對象只有一個2鍵),我們再次執行所有相同的步驟。

查看object.__getitem__文檔,開始。

class AutoVivification(dict)聲明使AutoVivification成為dict的子類,因此它的行為與dict相同,除非它明確地覆蓋某些行為 - 正如此類在覆蓋__getitem__時所做的那樣。

dict.__getitem__(self, item)的調用通常會被寫為:

super(AutoVivification, self).__getitem__(item)

(至少在Python 2.x中; Python 3有更好的語法。)無論哪種方式,它的作用是嘗試讓默認的dict行為運行,但是在不起作用的情況下實現回退。

type(self)()首先查找與self實例對應的類對象,然后調用類對象 - 在這種情況下與編寫AutoVivification()相同,這應該看起來更熟悉。

希望能為你清理它!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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