Cómo hacer que los decoradores se enciendan o apaguen opcionalmente
Estoy preguntando, dada una función con un decorador, ¿es posible ejecutar la función sin invocar la llamada del decorador?
Dada una funciónfoo
, ¿es posible activar o desactivar opcionalmente un decorador en él?
Dado
@decorator
def foo():
//do_somthing
¿Es posible correrfoo
condecorator
¿Apagado?
Es posible que exista alguna función en la que desee ejecutarlo con o sin el decorador. Por ejemplo (y no es bueno, ya que implica un almacenamiento en caché eficiente) apague el almacenamiento en caché basado en decorador en unfactorial(n)
función.
Mi pregunta es similar a esta preguntaOpcionalmente use decoradores en métodos de clase. Discute una buena aplicación de encendido / apagado del decorador (exponiendo como una api);
si tuviera que usar una función, digamosgoo
y dar la opción de ejecutargoo
con o sin un decorador, probé una forma primitiva y hack para lograr esta funcionalidad opcional de encendido / apagado del decorador de la siguiente manera:
# this is the decorator class that executes the function `goo`
class deco(object):
def __init__(self, attr):
print "I am initialized"
self.fn = None
# some args you may wana pass
self.attr = attr
# lets say you want these attributes to persist
self.cid = self.attr['cid']
self.vid = 0
def __call__(self, f):
# the call executes and returns another inner wrapper
def wrap(*args):
# this executes main function - see closure
self.fn = f
self.vid = args[0]
self.closure(*args)
return wrap
def closure(self, *args):
n = args[0]
self.cid[n] = self.vid
#goo = deco(fn, attr)
print 'n',n
# executes function `goo`
self.fn(*args)
class gooClass(object):
class that instantias and wraps `goo`around
def __init__(self, attr, deco):
'''
@param:
- attr: some mutable data structure
- deco: True or False. Whether to run decorator or not
'''
self.attr = attr
self.deco = deco
def __call__(self, *args):
if self.deco:
# initiate deco class with passed args
foo = deco(self.attr)
# now pass the `goo` function to the wrapper inside foo.__class__.__call__
foo = foo(self.goo)
return foo(*args)
else:
# execute w/o decorator
return self.goo(*args)
def goo(self, n):
# recursive goo
if n>0:
print 'in goo',n
#print n
# to recurse, I recreate the whole scene starting with the class
# because of this the args in `deco` Class init never persist
too = gooClass(self.attr, self.deco)
return too(n-1)
else: return n
def Fn(n, decoBool):
# this function is where to start running from
attr = {}
cid = [0]*(n+1)
attr['cid'] = cid
#following wud work too but defeat the purpose - have to define again! foo is goo actually
#@deco(attr)
#def foo(n):
# if n>0:
# print 'in foo',n
# #print n
# return foo(n-1)
# else: return n
#return foo(n), attr
# create the gooClass and execute `goo` method instance
foo = gooClass(attr, decoBool)
print foo(n)
return foo
res = Fn(5, True)
print res.attr
print "="*10
res = Fn(5, False)
print res.attr
que salidas:
I am initialized
n 5
in goo 5
I am initialized
n 4
in goo 4
I am initialized
n 3
in goo 3
I am initialized
n 2
in goo 2
I am initialized
n 1
in goo 1
I am initialized
n 0
None
{'cid': [0, 1, 2, 3, 4, 5]}
==========
in goo 5
in goo 4
in goo 3
in goo 2
in goo 1
0
{'cid': [0, 0, 0, 0, 0, 0]}
que técnicamente funciona, pero creo que es un truco de arranque. no pitónico Y cada vez que se crea una nueva clase de forma recursiva.
La pregunta se mantiene y no pude encontrar una respuesta relevante aquí, así que creé esto, ¿hay alguna forma de activar / desactivar decoradores opcionalmente?