J'ai le programme suivant:
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])
Ce que je m'attends à ce que ce programme fasse: il parcourt les clés du dictionnaire, qui comprend une liste intégrée d'un «nombre» (ie 1,1,3,6) et «unité» (ie semaines et mois), et extrait le valeur (ou taux) correcte. Actuellement, je reçois une erreur avec la ligne print deposits([n,unit])
.
Voici l'erreur que j'obtiens:
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
Le nom de mon fichier est TestFunction.py
Je connais un moyen de contourner ce problème, c'est là que je convertis le dictionnaire en deux listes comme suit:
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]
Mais cela n'a pas l'air aussi bien rangé ni aussi sophistiqué. Je serais vraiment reconnaissant pour vos conseils.
3 réponses
Dépôts est un dictionnaire avec des clés et des valeurs. La référence d'un dictionnaire est
value = mydict[key]
Ainsi, étant donné n et l'unité, vous obtenez que ql.Period (n, unité) renvoie un type de <class 'QuantLib.QuantLib.Period'>
. Le résultat de ql.period(1, ql.Weekly)
par exemple serait 1W.
Il semblerait que s'il est converti en chaîne, il serait alors utilisable comme clé.
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
Mettre à jour par commentaires: il ressemble à la classe Period
implémentée __hash__
de manière incorrecte, donc il n'obéit pas à l'invariant de hachage requis par Python (en particulier, les objets qui se comparent égaux doivent avoir un hachage de la même valeur). Selon votre commentaire, lorsque vous exécutez:
p1 = ql.Period(1,ql.Weeks)
p2 = ql.Period(1,ql.Weeks)
if (p1 == p2): k = 5*2
else: k = 0
Vous obtenez 10, donc p1==p2
est True
.
Lorsque vous exécutez:
if (hash(p1) == hash(p2)): b = 5*2
else: b = 0
Vous obtenez 0, donc hash(p1) == hash(p2)
est False
. Il s'agit d'une violation claire des règles Python, ce qui fait que le type apparaît comme une clé légale pour un dict
(ou une valeur dans un set
), mais se comporter incorrectement. Fondamentalement, vous ne pouvez pas utiliser les Period
s comme clés sans que les gens de QuantLib corrigent cela, ou ne font pas de choses terribles pour contourner cela (et des choses vraiment terribles si Period
est un type d'extension C, ce qui semble probablement car QuantLib est apparemment un wrapper SWIG).
Si les Period
unités se comportent correctement, je recommanderais de travailler avec tuple
s des nombres et des unités appariés la plupart du temps, et de ne convertir en Period
s que lorsque vous avez besoin d'un fonction Period
particulière. Votre dict
serait donc:
deposits = {(1,ql.Weeks): 0.0023,
(1,ql.Months): 0.0032,
(3,ql.Months): 0.0045,
(6,ql.Months): 0.0056}
Et votre boucle serait:
for n, unit in [(1,ql.Weeks),(1,ql.Months),(3,ql.Months),(6,ql.Months)]:
print deposits[n, unit]
Si cela échoue toujours, alors même les types d'unités de base sont cassés, et vous ne pouvez tout simplement pas les utiliser du tout.
Si les clés sont des ql.Period
, vous devez rechercher à l'aide de ql.Period
s (sauf si Period
est la sous-classe tuple
). Vous devez également utiliser des crochets pour la recherche dict
, pas des parenthèses.
Si ql.Period
est un namedtuple
ou similaire, vous pouvez simplement faire des tuple
recherches (les list
ne peuvent pas être des dict
clés, car elles sont mutables ):
for n, unit in [(1,ql.Weeks),(1,ql.Months),(3,ql.Months),(6,ql.Months)]:
print deposits[n, unit]
Si ql.Period
n'est pas une sous-classe tuple
, vous pouvez faire:
for n, unit in [(1,ql.Weeks),(1,ql.Months),(3,ql.Months),(6,ql.Months)]:
print deposits[ql.Period(n, unit)]
Ou pour faire les périodes dans la boucle,
import itertools
for period in itertools.starmap(ql.Period, [(1,ql.Weeks),(1,ql.Months),(3,ql.Months),(6,ql.Months)]):
print deposits[period]
En plus des problèmes de syntaxe que d'autres ont identifiés, je suppose que votre objet ql.Period
n'est pas hachable; les clés des dictionnaires doivent être des objets lavables. Voici un copier-coller direct de cette réponse, qui explique bien la situation.
>>> 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
Que se passe-t-il lorsque vous essayez hash(ql.Period(1,ql.Weeks))
? Un TypeError
similaire? Si vous contrôliez QuantLib
, vous pourriez éventuellement ajouter un __hash__
méthode, afin qu'ils puissent être utilisés dans les dictionnaires. Mais je vois qu'un tel module existe sur pypi, donc je suppose que vous l'utilisez plutôt que de l'écrire.
Vous pouvez toujours patch singe ces objets pour leur donner un {{X0} } méthode:
# 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
Questions connexes
Questions liées
De nouvelles questions
python
Python est un langage de programmation multi-paradigme, typé dynamiquement et polyvalent. Il est conçu pour être rapide à apprendre, comprendre, utiliser et appliquer une syntaxe propre et uniforme. Veuillez noter que Python 2 est officiellement hors support à partir du 01-01-2020. Néanmoins, pour les questions Python spécifiques à la version, ajoutez la balise [python-2.7] ou [python-3.x]. Lorsque vous utilisez une variante Python (par exemple, Jython, PyPy) ou une bibliothèque (par exemple, Pandas et NumPy), veuillez l'inclure dans les balises.