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