Search code examples
pythonruntimelanguage-featuresdecorator

Is it possible to replace a Python function/method decorator at runtime?


If I have a function :


@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()

Is it possible to replace a decorator at runtime?


Solution

  • I don't know if there's a way to "replace" a decorator once it has been applied, but I guess that probably there's not, because the function has already been changed.

    You might, anyway, apply a decorator at runtime based on some condition:

    #!/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)