2009-09-19 9 views
0

Modification parce que le code initial était confus.Les décorateurs ne devraient pas avoir d'effets secondaires?

Je suppose que ces deux choses à même,

#I would use either of these 
#Option 1 
def bar(*args): 
    pass 
foo = deco(bar) 

#Option2 
@deco 
def foo(*args): 
    pass 

Toutefois, si les décorateurs deco a des effets secondaires, ce n'est pas garantie. En partcicular, ce fut ma ecpectation former un décorateur (pas d'effet secondaire), et je suis tombé sur un avec le côté effct et a été mordu par elle,

#Option1 
def bar(*args): 
    pass 
foo = register.filter(bar) 

#Option 2 
@register.filter 
def foo(val, arg): 
    pass 

Alors est mon attente mal, ou est django étant incompatible avec la les meilleures pratiques?

+0

Un fil à partir de 2004 par Jim Hugunin semble penser. http://mail.python.org/pipermail/python-dev/2004-April/044133.html – agiliq

+0

Une question a été posée ci-dessous, ajoutant ainsi que, la barre est un autre appelable. – agiliq

+0

vos exemples n'ont aucun sens, parce que vous jetez le foo que vous définissez. vous utiliseriez la déco pour décorer foo, donc vous obtenez un nouveau truc. – hop

Répondre

2

En fait, ces deux sont exactement les mêmes:

def foo(*args): 
    pass 
foo = deco(foo) 

@deco 
def foo(*args): 
    pass 

Si vous voulez décorer bar et appeler foo, foo = deco(bar) est la bonne façon. Il dit: "décorer cette chose précédemment définie appelée bar et l'appeler foo". Le point de la syntaxe du décorateur est d'indiquer la fonction d'emballage avant la définition, pas de le renommer.

À moins que vous n'ayez besoin d'utiliser bar plus tard, il n'y a aucune raison d'appeler la fonction non décorée avec un nom différent. En faisant cela, vous perdez précisément la possibilité d'utiliser la syntaxe du décorateur sucre.

deco n'a pas besoin d'être une fonction. Il peut s'agir d'un objet avec une méthode __call__, utile pour encapsuler les effets secondaires.

+0

@roberto: exactement. Ma question est, devrait-elle être exactement la même chose que 'foo = deco (bar)' – agiliq

+0

Que diable est 'bar'? Le décorateur 'deco' encapsule la méthode' foo', et équivaut exactement à 'foo = deco (foo)'. Pourquoi continuez-vous à poser des questions sur 'foo = deco (bar)'? Peut-être que cette idée fausse est la question fondamentale. – PaulMcG

+0

bar est un autre appelable. Je veux lier la valeur retirée de deco (bar) à foo. – agiliq

0

Vos exemples n'expriment pas la même chose dans tous les cas! Pourquoi insistez-vous sur l'utilisation de la barre?

Prenez votre premier exemple:

#Option 1 
def bar(*args): 
    pass 
foo = deco(bar) 

#Option2 
@deco 
def foo(*args): 
    pass 

Option 1 ne (littéralement)

foo = deco(bar) 

, mais l'option 2 est l'équivalent de

foo = deco(foo) 

Tu ne peux pas voir la différence Là? Donc, en bref, oui: votre hypothèse et vos attentes sont fausses.

Si vous avez besoin de la version undecorated votre fonction, ainsi que celle décorée, juste l'enregistrer au préalable:

def foo(*args): 
    pass 
bar = foo 
foo = deco(foo) 
+0

> Pourquoi insistez-vous sur l'utilisation de la barre? Parce que j'ai besoin d'accéder à la fois à la fonction décorée et non décorée. Mes hypothèses sont (évidemment) fausses. Mais pourquoi mes attentes sont-elles fausses? – agiliq

+0

pourquoi voudriez-vous vous limiter avec une telle règle arbitraire? – hop

+0

est-ce que Library(). Register() fait même quelque chose à func, sauf l'enregistrer? foo devrait être le même avant et après ... – hop

Questions connexes