Say, we have a function foo
, which takes another function bar
as an argument and does something based on bar
's signature, and, sadly, throws an error when bar
has default arguments. I want to use foo
with functions, say, bar1
,bar2
,...bar100
, all of which have default arguments. All of the aforementioned functions are from an outer library which I cannot change. There are too many bar
s to rewrite each of them as a lambda statement. The only way is to remove all bound arguments from these functions. And there's exec, but I'm not that desperate yet.
I know there's a module called inspect in python which works with function signatures, I came up with the following code:
from inspect import signature
from functools import partial
def remove_default_args(func, **kwargs):
func = partial(func, **kwargs)
sg = signature(func)
unbound_parameters = [p for p in sg.parameters.values() if p.default == p.empty]
func.__signature__ = sg.replace(parameters=unbound_parameters)
return func
Is there any better way to do this, without inspect? I ask since I know inspect
is generally frowned upon, as it only changes the metadata.
Default argument values are stored in the __defaults__
and __kwdefaults__
attributes, which are writable. You can simply set them "back" to None
to remove all defaults.
>>> def foo(x=3, *, y=5):
... pass
...
>>> foo()
>>> foo.__defaults__, foo.__kwdefaults__
((3,), {'y': 5})
>>> foo.__defaults__ = None
>>> foo.__kwdefaults__ = None
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() missing 1 required positional argument: 'x'