[英]Unhashable type 'dict' error in memoize decorator
我正在編寫一個 memoize 裝飾器,但是在一個簡單的示例中嘗試它時,我得到了一個不可散列的類型“dict”錯誤。 這是我的代碼:
def memoize(func):
"""Store the results of the decorated function for fast lookup
"""
# Store results in a dict that maps arguments to results
cache = {}
# Define the wrapper function to return
def wrapper(*args, **kwargs):
# If these arguments haven't been seen before,
if (args, kwargs) not in cache:
# Call func() and store the result.
cache[(args, kwargs)] = func(*args, **kwargs)
return cache[(args, kwargs)]
return wrapper
這是一個簡單的 function 用於測試我的裝飾器:
import time
@memoize
def slow_func(a, b):
print("Sleeping...")
time.sleep(5)
return a+ b
slow_func(2, 7)
我最終得到這個錯誤:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_17888/3627587563.py in <module>
----> 1 slow_func(2, 7)
~\AppData\Local\Temp/ipykernel_17888/52581778.py in wrapper(*args, **kwargs)
7 def wrapper(*args, **kwargs):
8 # If these arguments haven't been seen before,
----> 9 if (args, kwargs) not in cache:
10 # Call func() and store the result.
11 cache[(args, kwargs)] = func(*args, **kwargs)
TypeError: unhashable type: 'dict'
我測試以防萬一我的 Python 是否正常工作: (2, 3) not in {}
導致正確的 output True
。
任何幫助,將不勝感激!
這引發異常的原因是,當您在 function 定義中使用**kwargs
時,變量kwargs
將屬於dict
類型。 字典是可變的和不可散列的; 這意味着它們不能用作另一個dict
中的鍵或用作set
中的元素。 當您執行cache[(args, kwargs)]
時,您試圖將 dict kwargs
用作 dict cache
中鍵的一部分,因此會出現錯誤。 如果您不需要自己實現 memoization function,您可以使用標准庫中functools
模塊中的lru_cache
function:
import functools, time
@functools.lru_cache
def slow_func(a, b):
print("Sleeping...")
time.sleep(5)
return a + b
t1 = time.monotonic()
slow_func(2, 7)
slow_func(2, 7)
t2 = time.monotonic()
print("Total time:", t2-t1)
印刷:
python t.py
Sleeping...
Total time: 5.005460884000058
在這種情況下,args 是(2, 3)
並且kwargs
是一個空字典(因為您沒有將任何命名的 args 傳遞到您的 function 調用中)。 但是,字典是可變的,不能用作另一個字典中的鍵,因此不是可hashable
的。
那么我們從這里到哪里 go 呢? 您可以完全忽略kwargs
,但是當args
本身包含字典時,您仍然會遇到問題: slow_func({"key": 1})
會導致相同的問題,因為 arg {key: 1}
本身就是字典。
在我看來,這似乎是一個非常特定類型的 function 的記憶。 意思是,這樣的包裝不能盲目地應用於任何 function。 arguments 的順序重要嗎? 如果是這樣,僅記住存在的 args 是不夠的。 在 args 周圍放置一些防護欄將使記憶變得可預測且更容易。
這里最簡單的解決方法是只允許kwargs
的某些種類或參數或值。 例如:所有 args 和所有kwarg
值必須是float
s 或int
s。
話雖如此,如果您還需要記憶kwargs
,則必須解析字典和args
中的任何dict
類型,並將格式存儲為某種可散列格式。
想到的一種方法是,您可以將解析的 args 和 kwargs 存儲在自定義 class 中,該自定義 class 實現了__hash__
數據方法(更多信息在這里: 制作 python 用戶定義的 ZA2F2ED4F8EBC2CBB4C21A29DC4並將其存儲在您的排序緩存中。 但這一切都取決於你打算如何使用這個memoize
裝飾器。
編輯:話雖如此,正如其他人指出的那樣,標准 functools 庫已經包含一些用於緩存的實用方法: https://docs.python.org/3/library/functools.html#functools.cache
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.