簡體   English   中英

選擇鍵以跟蹤已在遞歸調用中運行的功能

[英]The choice of key to keep track of functions already running in recursive calls

Python 3.2中引入的reprlib模塊中的recursive_repr函數具有以下源代碼

def recursive_repr(fillvalue='...'):
    'Decorator to make a repr function return fillvalue for a recursive call'

    def decorating_function(user_function):
        repr_running = set()

        def wrapper(self):
            key = id(self), get_ident()
            if key in repr_running:
                return fillvalue
            repr_running.add(key)
            try:
                result = user_function(self)
            finally:
                repr_running.discard(key)
            return result

        # Can't use functools.wraps() here because of bootstrap issues
        wrapper.__module__ = getattr(user_function, '__module__')
        wrapper.__doc__ = getattr(user_function, '__doc__')
        wrapper.__name__ = getattr(user_function, '__name__')
        wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
        return wrapper

    return decorating_function

標識特定__repr__函數的key設置為(id(self), get_ident())

為什么self本身不被用作鑰匙? 為什么需要get_ident

考慮以下代碼:

a = []
b = []
a.append(b)
b.append(a)
a == b

這會導致堆棧溢出。 但是算法需要安全處理這種情況。 如果將self放入集合中,它將使用==進行比較,該算法將失敗。 因此,我們改用id(self)而不嘗試檢查對象的相等性。 我們只關心它是否是完全相同的對象。

至於get_indent ,請考慮如果兩個線程嘗試同時使用該代碼,則該算法中會發生什么。 repr_running集在所有線程之間共享。 但是,如果有多個線程開始從該集合中添加和刪除元素,則無法確定會發生什么。 get_ident()對於運行它的線程是唯一的,因此通過將其與鍵一起使用,我們知道所有線程都將使用不同的鍵並且可以。

暫無
暫無

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

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