我有以下程序:
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])
我希望这个程序能做的是:它循环遍历字典键,其中包含一个嵌入的'number'列表(即1,1,3,6)和'unit'(即周和月),并提取正确的值(或速率)。目前,我在第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]
但它看起来并不那么整洁或复杂。我非常感谢你的建议。
答案 0 :(得分:1)
更新:Period
类似乎错误地实施了__hash__
,因此它不会服从the hash invariant required by 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
中的值)的合法密钥,但行为不正确。基本上,你不能使用Period
作为键,而不需要QuantLib人员解决这个问题,或者做一些可怕的事情来处理它(如果Period
是C扩展类型,那真的很糟糕,这似乎很可能是因为QuantLib显然是一个SWIG包装器。)
如果Period
单位行为正常,我建议大部分时间使用配对计数和单位的tuple
,并且只在转换为Period
时您需要特定的Period
功能。所以你的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
,则需要使用ql.Period
进行查找(除非Period
为tuple
子类)。您还需要使用括号进行dict
查找,而不是括号。
如果ql.Period
是namedtuple
之类,您可以tuple
查找(list
不能成为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]
答案 1 :(得分:0)
deposit是一个包含键和值的字典。字典的引用是
value = mydict[key]
因此,给定n和单位,你得到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
答案 2 :(得分:0)
除了其他人发现的语法问题之外,我的猜测是你的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__
method,以便可以在词典中使用它们。但是我看到pypi上存在这样一个模块,所以我猜你只是用它而不是写它。
您仍然可以monkey patch这些对象为其提供__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