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.

-1
MacMavin 7 mars 2016 à 20:20

3 réponses

Meilleure réponse

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
0
sabbahillel 7 mars 2016 à 20:51

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]
1
ShadowRanger 7 mars 2016 à 19:28

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
0
Community 23 mai 2017 à 10:28