-1

我有以下程序:

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]

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

4

3 回答 3

1

根据评论更新:看起来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 规则,这使得该类型看起来是 a dict(或 a 中的值set)的合法键,但行为不正确。Period基本上,如果没有QuantLib 人员修复这个问题,或者做一些糟糕的事情来解决它(如果Period是 C 扩展类型,这似乎很可能,因为 QuantLib 显然是一个 SWIG 包装器,所以你不能使用s 作为键)。

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

如果ql.Period是 anamedtuple或类似的,您可以只进行tuple查找(lists 不能是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]

于 2016-03-07T17:30:08.273 回答
0

deposit 是一个包含键和值的字典。字典的参考是

 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
于 2016-03-07T17:26:36.847 回答
0

除了其他人发现的语法问题外,我的猜测是您的ql.Period对象不可散列;字典的键需要是可散列的对象。这是此答案的直接复制和过去,很好地解释了这种情况。

>>> 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
于 2016-03-07T19:07:34.627 回答