Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redefine defaults arguments of a python function by name

Tags:

python

For efficiency purposes, I don't want to use functools.partial for this task (adds overhead when using the function). I want to redefine a function's copy defaults arguments, by name.

For the moment I have the following :

import types


# http://stackoverflow.com/questions/6527633/how-can-i-make-a-deepcopy-of-a-function-in-python
def copy_func(f, name=None, defaults=None):
    return types.FunctionType(f.__code__, f.__globals__, name or f.__name__, defaults or f.__defaults__, f.__closure__)


def f(a, b, c):
    return 'a = {}, b = {} and  c = {}'.format(a,b,c)

i = copy_func(f, 'i', (4,5))

print(f(3,4,5))
print(i('should be a'))

Can we modify the copy_func tool to be called like so :

i = copy_func(f, a = 4, b = 5)

i.e, using the names of arguments from the original function.

Of course, if the arguments do not exists, I hope the function would yell at me ;)

like image 918
lrnv Avatar asked Sep 16 '25 20:09

lrnv


1 Answers

I believe you can do this:

import inspect

def copy_func(f, name=None, **defaults):
    args = inspect.getfullargspec(f).args
    arg_defaults = tuple(defaults.get(arg) for arg in args)

    return types.FunctionType(f.__code__, f.__globals__, name or f.__name__, arg_defaults or f.__defaults__, f.__closure__)

Since we need to provide a tuple (arg_defaults) for the defaults to FunctionType, we can generate this tuple by iterating through f's arguments and seeing which ones have a default provided in defaults. We use defaults.get instead of defaults[...] because a lack of a default is given as None to FunctionType.

copy_func(f, 'i', a = 4, b = 5)()

results in:

'a = 4, b = 5 and  c = None'

If you want the function to yell at you if defaults contains an invalid argument, you'd need to add this explicit condition between the declarations of args and arg_defaults:

if not all(arg in args for arg in defaults.keys()):
    raise ValueError("defaults contains invalid arguments")
like image 77
Mario Ishac Avatar answered Sep 19 '25 11:09

Mario Ishac