Geo*_*Geo 19 python language-features runtime decorator
如果我有一个功能:
@aDecorator
def myfunc1():
# do something here
if __name__ = "__main__":
# this will call the function and will use the decorator @aDecorator
myfunc1()
# now I want the @aDecorator to be replaced with the decorator @otherDecorator
# so that when this code executes, the function no longer goes through
# @aDecorator, but instead through @otherDecorator. How can I do this?
myfunc1()
Run Code Online (Sandbox Code Playgroud)
是否可以在运行时替换装饰器?
DNS*_*DNS 15
正如Miya所提到的,在解释器获得该函数声明之前,您可以在任何点上用另一个函数替换装饰器.但是,一旦将装饰器应用于该函数,我认为没有办法用另一个动态替换装饰器.例如:
@aDecorator
def myfunc1():
pass
# Oops! I didn't want that decorator after all!
myfunc1 = bDecorator(myfunc1)
Run Code Online (Sandbox Code Playgroud)
不起作用,因为myfunc1不再是你最初定义的函数; 它已被包裹.这里最好的方法是手动应用装饰器,oldskool-style,即:
def myfunc1():
pass
myfunc2 = aDecorator(myfunc1)
myfunc3 = bDecorator(myfunc1)
Run Code Online (Sandbox Code Playgroud)
编辑:或者,要更清楚一点,
def _tempFunc():
pass
myfunc1 = aDecorator(_tempFunc)
myfunc1()
myfunc1 = bDecorator(_tempFunc)
myfunc1()
Run Code Online (Sandbox Code Playgroud)
我不知道是否有一种方法可以在应用装饰器后"替换"它,但我想可能没有,因为该功能已被更改.
无论如何,您可能会在运行时根据某些条件应用装饰器:
#!/usr/bin/env python
class PrintCallInfo:
def __init__(self,f):
self.f = f
def __call__(self,*args,**kwargs):
print "-->",self.f.__name__,args,kwargs
r = self.f(*args,**kwargs)
print "<--",self.f.__name__,"returned: ",r
return r
# the condition to modify the function...
some_condition=True
def my_decorator(f):
if (some_condition): # modify the function
return PrintCallInfo(f)
else: # leave it as it is
return f
@my_decorator
def foo():
print "foo"
@my_decorator
def bar(s):
print "hello",s
return s
@my_decorator
def foobar(x=1,y=2):
print x,y
return x + y
foo()
bar("world")
foobar(y=5)
Run Code Online (Sandbox Code Playgroud)