2011-11-29 6 views
1

J'ai un décorateur comme celui-ci:Argument de fonction ayant une valeur qui est ni transmise par l'appelant, ni valeur par défaut

def region_required(view_func): 
    def new_view(request, ctx = {}, *args, **kw): 
     import pdb; pdb.set_trace() 
     ctx['regions'] = Region.objects.all() 
     return view_func(request, context=ctx, *args, **kw) 
    return new_view 

Je l'utilise pour décorer les fonctions de vue.

Aujourd'hui, j'ai remarqué quelque chose de vraiment étrange, l'argument ctx (contexte) a parfois des données qui appartiennent à la dernière requête HTTP. Puis je l'ai réduit à ce décorateur et j'ai trouvé que ctx avait une valeur quand ça devrait être {} ici.

Donc, j'ai mis un point d'arrêt, et monte d'un niveau, puis j'ai trouvé que son appelant ne lui passe rien du tout.

Comment un argument peut-il avoir une valeur qui n'est pas transmise par l'appelant ni par la valeur par défaut?

Répondre

5

Vous utilisez un argument mutable en tant que paramètre par défaut. Chaque fois qu'il est appelé sans cet argument, il comprendra celui que vous avez fourni, y compris les modifications préalables. Utilisez None comme valeur par défaut, vérifiez-la, et si is None, affectez la dict vide dans le corps de la fonction.

def region_required(view_func): 
    def new_view(request, ctx=None, *args, **kw): 
     if ctx is None: 
      ctx = {} 
     import pdb; pdb.set_trace() 
     ctx['regions'] = Region.objects.all() 
     return view_func(request, context=ctx, *args, **kw) 
    return new_view 
+0

wow, j'utilise Python depuis des années, mais il y a encore des choses à apprendre. – ablmf

0

ctx reçoit probablement le premier argument de la fonction encapsulée. Vous ne pouvez pas avoir un mot clé arg suivi de * args. En ce qui concerne l'appelant, ctx est juste un autre argument.

Par exemple:

my_func(request, 1, 2, 3) 

se traduira par CTX étant affecté 1. CTX doit être considérée comme faisant partie de kwargs.

ctx = kwargs.get('ctx', {}) 
Questions connexes