views:

148

answers:

4

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

A: 

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
Jeff
+4  A: 

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
SilentGhost
A: 

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

http://stackoverflow.com/questions/1261875/python-nonlocal-statement

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

Dustin Getz
A: 

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):
    ....
hop
whats that @ line do?
Dustin Getz
that's how a decorator is applied to a function.
hop
thanks, hop. that's closer to what i was thinking originally
marcopolo1010