0

I'm looking for a way to decorate an arbitrary python function, so that an alternate function is called instead of the original, with all parameters passed as a list or dict.

More precisely, something like this (where f is any function, and replacement_f takes a list and a dict):

def replace_func(f, replacement_f):
    def new_f(*args, **kwargs):
        replacement_f(args, kwargs)
    return new_f

However, I cannot reference replacement_f inside new_f. And I can't use the standard trick of passing replacement_f to new_f as the default for a different parameter, because I'm using the *args and **kwargs variable argument lists.

The location where the original function is called cannot change, and will accept both positional and named parameters.

I fear that isn't very clear, but I'm happy to clarify if needed.

Thanks

2
  • you are right: this is not clear. i think you don't need to change the call of the original function, but rather its definition. if you can't change that, you probably can't decorate it either. Commented Aug 18, 2009 at 17:58
  • thanks all. I was making this far too difficult, I can just replace the function without all the *args, **kwargs hassle. Also, I think the scope rules have changed since Python 1.x, now I can reference a variable from the outer function inside the inner function definition. Commented Aug 18, 2009 at 18:08

4 Answers 4

4

why don't you just try:

f = replacement_f

example:

>>> def rep(*args):
    print(*args, sep=' -- ')

>>> def ori(*args):
    print(args)

>>> ori('dfef', 32)
('dfef', 32)
>>> ori = rep
>>> ori('dfef', 32)
dfef -- 32
Sign up to request clarification or add additional context in comments.

Comments

1

Although I think SilentGhost's answer is the best solution if it works for you, for the sake of completeness, here is the correct version of what you where trying to do:

To define a decorator that takes an argument, you have to introduce an additional level:

def replace_function(repl):
    def deco(f):
        def inner_f(*args, **kwargs):
            repl(*args, **kwargs)

        return inner_f
    return deco

Now you can use the decorator with an argument:

@replace_function(replacement_f)
def original_function(*args, **kwargs):
    ....

2 Comments

that's how a decorator is applied to a function.
thanks, hop. that's closer to what i was thinking originally
0

If I understand this correctly, you want to pass all arguments from one function to another.

Simply do:

def replace_func(f, replacement_f):
    def new_f(*args, **kwargs):
        replacement_f(*args, **kwargs) # args & kwargs will be expanded
    return new_f

Comments

0

does this do what you mean? Untested

def replace_func(f, replacement_f):
    nonlocal replacement_f  #<<<<<<<<<<<<<<<py3k magic
    def new_f(*args, **kwargs):
        replacement_f(*args, **kwargs) # args & kwargs will be expanded
    replacement_f = new_f

Python nonlocal statement

edit: its a start, im confused exactly what you want, but i think nonlocal will help

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.