使用作为列表的键从字典中提取值

时间:2016-03-07 17:20:19

标签: python dictionary quantlib-swig

我有以下程序:

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]

但它看起来并不那么整洁或复杂。我非常感谢你的建议。

3 个答案:

答案 0 :(得分:1)

comments

更新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==p2True

当你跑步时:

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进行查找(除非Periodtuple子类)。您还需要使用括号进行dict查找,而不是括号。

如果ql.Periodnamedtuple之类,您可以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