How to replace Python function while supporting all passed in parameters
Question:
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
Answers:
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
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
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
edit: its a start, im confused exactly what you want, but i think nonlocal will help
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):
....
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
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
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
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
edit: its a start, im confused exactly what you want, but i think nonlocal will help
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):
....