[英]Extract value from a dictionary using key that is a list
我有以下程序:
import QuantLib as ql
deposits = {ql.Period(1,ql.Weeks): 0.0023,
ql.Period(1,ql.Months): 0.0032,
ql.Period(3,ql.Months): 0.0045,
ql.Period(6,ql.Months): 0.0056}
for n, unit in [(1,ql.Weeks),(1,ql.Months),(3,ql.Months),(6,ql.Months)]:
print deposits([n,unit])
我希望這個程序做的是:它遍歷字典鍵,它包含一個“數字”(即 1、1、3、6)和“單位”(即周和月)的嵌入列表,並提取正確的值(或比率)。 目前,我在行print deposits([n,unit])
遇到錯誤。
這是我得到的錯誤:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Anaconda2\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 699, in runfile
execfile(filename, namespace)
File "C:\Anaconda2\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 74, in execfile
exec(compile(scripttext, filename, 'exec'), glob, loc)
File "TestFunction.py", line 16, in <module>
print deposits([n,unit])
TypeError: 'dict' object is not callable
我的文件名為TestFunction.py
我知道解決這個問題的方法,我將字典轉換為兩個列表,如下所示:
depoMaturities = [ql.Period(1,ql.Weeks),
ql.Period(1,ql.Months),
ql.Period(3,ql.Months),
ql.Period(6,ql.Months)]
depoRates = [0.0023,
0.0032,
0.0045,
0.0056]
但它看起來並不那么整潔或復雜。 我真的很感激你的建議。
根據評論更新:看起來Period
類不正確地實現了__hash__
,因此它不遵守Python 所需的散列不變量(特別是,比較相等的對象應該散列到相同的值)。 根據您的評論,當您運行時:
p1 = ql.Period(1,ql.Weeks)
p2 = ql.Period(1,ql.Weeks)
if (p1 == p2): k = 5*2
else: k = 0
你得到 10,所以p1==p2
是True
。
當你運行時:
if (hash(p1) == hash(p2)): b = 5*2
else: b = 0
你得到 0,所以hash(p1) == hash(p2)
是False
。 這明顯違反了 Python 規則,這使得該類型看起來是dict
(或set
值)的合法鍵,但行為不正確。 基本上,你不能在沒有 QuantLib 的人解決這個問題的情況下使用Period
s 作為鍵,或者做一些可怕的事情來解決它(如果Period
是一個 C 擴展類型,這真的很糟糕,這似乎很可能,因為 QuantLib 顯然是一個 SWIG 包裝器)。
如果Period
單位行為正常,我建議大部分時間使用配對計數和單位的tuple
s,並且僅在您需要特定Period
功能時才轉換為Period
s。 所以你的dict
是:
deposits = {(1,ql.Weeks): 0.0023,
(1,ql.Months): 0.0032,
(3,ql.Months): 0.0045,
(6,ql.Months): 0.0056}
你的循環將是:
for n, unit in [(1,ql.Weeks),(1,ql.Months),(3,ql.Months),(6,ql.Months)]:
print deposits[n, unit]
如果仍然失敗,那么即使是基本單位類型也已損壞,您根本無法使用它們。
如果鍵是 ql.Period
s,則需要使用ql.Period
s 進行查找(除非Period
是tuple
子類)。您還需要使用括號進行dict
查找,而不是括號。
如果ql.Period
是namedtuple
或類似的,你可以做tuple
查找( list
s不能是dict
鍵,因為它們是可變的):
for n, unit in [(1,ql.Weeks),(1,ql.Months),(3,ql.Months),(6,ql.Months)]: print deposits[n, unit]
如果ql.Period
不是tuple
子類,您可以執行以下操作:
for n, unit in [(1,ql.Weeks),(1,ql.Months),(3,ql.Months),(6,ql.Months)]: print deposits[ql.Period(n, unit)]
或在循環中制作句點,
import itertools for period in itertools.starmap(ql.Period, [(1,ql.Weeks),(1,ql.Months),(3,ql.Months),(6,ql.Months)]): print deposits[period]
存款是一個帶有鍵和值的字典。 字典的參考是
value = mydict[key]
因此,給定 n 和 unit 你會得到 ql.Period(n, unit) 返回<class 'QuantLib.QuantLib.Period'>
。 例如, ql.period(1, ql.Weekly)
的結果將是 1W。
看起來,如果將其轉換為字符串,則它可以用作鍵。
deposits = {str(ql.Period(1,ql.Weeks)): 0.0023,
str(ql.Period(1,ql.Months)): 0.0032,
str(ql.Period(3,ql.Months)): 0.0045,
str(ql.Period(6,ql.Months)): 0.0056}
value = deposits[str(ql.Period(n, unit))]
print value
除了其他人已經確定的語法問題之外,我的猜測是您的ql.Period
對象不可散列; 字典的鍵需要是可散列的對象。 這是this answer的直接復制和過去,它很好地解釋了這種情況。
>>> a = {}
>>> b = ['some', 'list']
>>> hash(b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list objects are unhashable
>>> a[b] = 'some'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list objects are unhashable
當你嘗試hash(ql.Period(1,ql.Weeks))
時會發生什么? 類似的TypeError
? 如果您可以控制QuantLib
,您可能會添加一個__hash__
方法,以便它們可以在字典中使用。 但是我看到pypi上存在這樣一個模塊,所以我猜你只是在使用它而不是編寫它。
您仍然可以對這些對象進行猴子修補,以給它們一個__hash__
方法:
# First define a function to add on as a method
def hash_method(period):
hash_value = # some code that produces a unique hash, based on
# the data contained in the `period` object
return hash_value
# Now, monkey patch the ql.Period object by giving it this method
ql.Period.__hash__ = hash_method
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.