使用作为列表的键从字典中提取值
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])
我希望这个程序做的是:它循环遍历字典键,它包含一个 '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]
但它看起来并不那么整洁或精致。非常感谢您的建议。
deposits 是一个包含键和值的字典。字典的引用是
value = mydict[key]
因此给定 n 和单位你得到 ql.Period(n, unit) returns 一种 <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
Update per : It looks like the Period
class implemented __hash__
incorrectly, so it doesn't obey 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
的合法键(或 [=24= 中的值) ]), 但 行为 不正确。基本上,如果没有 QuantLib 人员修复这个问题,或者做一些糟糕的事情来解决它,你就不能使用 Period
s 作为键(如果 Period
是 C 扩展类型,这看起来真的很糟糕可能是因为 QuantLib 显然是一个 SWIG 包装器)。
如果 Period
单位表现正常,我建议大部分时间使用配对计数和单位的 tuple
s,并且仅在以下情况下转换为 Period
s您需要特定的 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]
如果还是不行,那就连基本的单位类型都坏了,根本就不能用
如果key是ql.Period
,需要用ql.Period
查找(除非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]
除了其他人已经确定的语法问题外,我的猜测是您的 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
我有以下程序:
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]
但它看起来并不那么整洁或精致。非常感谢您的建议。
deposits 是一个包含键和值的字典。字典的引用是
value = mydict[key]
因此给定 n 和单位你得到 ql.Period(n, unit) returns 一种 <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
Update per Period
class implemented __hash__
incorrectly, so it doesn't obey 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
的合法键(或 [=24= 中的值) ]), 但 行为 不正确。基本上,如果没有 QuantLib 人员修复这个问题,或者做一些糟糕的事情来解决它,你就不能使用 Period
s 作为键(如果 Period
是 C 扩展类型,这看起来真的很糟糕可能是因为 QuantLib 显然是一个 SWIG 包装器)。
如果 Period
单位表现正常,我建议大部分时间使用配对计数和单位的 tuple
s,并且仅在以下情况下转换为 Period
s您需要特定的 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]
如果还是不行,那就连基本的单位类型都坏了,根本就不能用
如果key是ql.Period
,需要用ql.Period
查找(除非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]
除了其他人已经确定的语法问题外,我的猜测是您的 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