3

I have put decorators in quotes as these aren't strict decorators by python standards although they need to act like one.

Let's say I have 3 decorators, f,g,h.

def f(x):
   return x+1

def g(x):
   return x+2

def h(x):
   return x * 3

and my "real" fn

def orig_fn(z):
   return z + 100

How can I modify orig_fn so that I can chain at runtime different combinations of f,g,h ?

If I use more than one of f,g,h then they should all be applied - ie orig_fn may return f(g(orig_fn(x)) .

I've tried something like (the real thing I'm doing is modifying a class function - hence the inclusion of MethodType). fn_chain would be something like [f,g] and I'm trying to solve this generically - current_fn is the original function found in the class.

 if fn_chain:
   print "-> creating chain"
   for fn in fn_chain:
     def modified_fn(self,*args,**kwargs):
       return fn(self, current_fn, *args,**kwargs)
                #current_fn = modified_fn

     setattr(cls,f_name,types.MethodType(modified_fn,cls))
3
  • What do you mean by "modify"? Do you want to change orig_fn so that it lets you specify other functions to chain? What kind of API are you looking for here? Commented Dec 3, 2015 at 18:06
  • At runtime, I wish to add various decorator type behaviour .. ie "f" might be a caching mechanism, g might be a debugging / display mechanism, etc etc Commented Dec 3, 2015 at 18:10
  • Caching sounds like something you'd need to do with an actual decorator. One that takes the function as input, not its return value. It needs to be able to prevent the orig_fn call from happening at all. Commented Dec 3, 2015 at 18:12

1 Answer 1

5

It's simple enough to build a function for composing other functions:

def compose(*funcs):
    # If we compose(f, g), we want to apply g first.
    funcs = funcs[::-1]

    def composition(val):
        for func in funcs:
            val = func(val)
        return val

    return composition

Then you can call compose(f, g, orig_fn) to get a function that does f(g(orig_fn(x))).

Sign up to request clarification or add additional context in comments.

1 Comment

Let me try that - I may have missed the obvious but that looks like what I need ... thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.