2010-09-22 18 views
3

Est-il possible de décorer une fonction en fonction d'une condition?Python3 décorer sous condition?

A'la:

if she.weight() == duck.weight(): 
    @burn 
def witch(): 
    pass 

Je me demande si la logique pourrait être utilisée (quand witch est appelé?) Pour savoir si oui ou non pour décorer witch avec @burn?

Si non, est-il possible de créer une condition dans le décorateur pour le même effet? (witch étant appelé non décoré.)

J'apprécie toute aide pour comprendre cela.

Répondre

3

Il est possible de enable/disable decorators par réaffectation.

def unchanged(func): 
    "This decorator doesn't add any behavior" 
    return func 

def disabled(func): 
    "This decorator disables the provided function, and does nothing" 
    def empty_func(*args,**kargs): 
     pass 
    return empty_func 

# define this as equivalent to unchanged, for nice symmetry with disabled 
enabled = unchanged 

# 
# Sample use 
# 

GLOBAL_ENABLE_FLAG = True 

state = enabled if GLOBAL_ENABLE_FLAG else disabled 
@state 
def special_function_foo(): 
    print "function was enabled" 
9

Vous pouvez créer un décorateur 'condition':

>>> def conditionally(dec, cond): 
    def resdec(f): 
     if not cond: 
      return f 
     return dec(f) 
    return resdec 

Exemple d'utilisation suit:

>>> def burn(f): 
    def blah(*args, **kwargs): 
     print 'hah' 
     return f(*args, **kwargs) 
    return blah 

>>> @conditionally(burn, True) 
def witch(): pass 
>>> witch() 
hah 

>>> @conditionally(burn, False) 
def witch(): pass 
>>> witch() 
+1

+1 J'aime plus que ma solution, car il garde avec le thème de décorateur, et semble assez propre, imo. – nilamo

+0

C'est une vieille réponse, mais est-ce que quelqu'un sait comment passer des arguments au décorateur conditionnellement emballé en utilisant ce modèle? –

4

Décorateurs ne sont que le sucre syntactique pour redéfinissant la fonction, ex:

def wrapper(f): 
    def inner(f, *args): 
     return f(*args) 
    return lambda *args: inner(f, *args) 

def foo(): 
    return 4 
foo = wrapper(foo) 

Ce qui signifie que vous pouvez le faire à l'ancienne, avant que le sucre syntactique existait:

def foo(): 
    return 4 
if [some_condition]: 
    foo = wrapper(foo)