I'm trying to understand the following about dealing with functions and their arguments:
def print_my_arg(func, *args, **kwargs):
func(*args, **kwargs)
if 'my_arg' in kwargs:
print(' my_arg = {}'.format(kwargs['my_arg']))
def foo(call_no, my_arg='Default Value'):
print('call_no = {}'.format(call_no) )
print_my_arg(foo, 0, my_arg='My Value 1')
print_my_arg(foo, 1, 'My Value 2')
print_my_arg(foo, 2)
Output:
call_no = 0
my_arg = My Value 1
call_no = 1 # I'd like to see 'My Value 2' here
call_no = 2 # I'd like to see 'Default Value' here
Obviously people are free to invoke functions in either of the ways shown above, which makes me wonder: why my_arg
doesn't go to kwargs
anyway? Isn't there a uniform way to access parameters by name (and not by position), which doesn't depend on the way the function was invoked?
Please note that:
I'm not interested in
print_my_args(func, call_no, my_arg)
, because I'm talking about the case where I don't know the signature offunc
in advance and yet I want to know if a particular parameter exists (by name).Clearly that's related to decorators, but I've written the example in a simpler way (or I hope so).
EDIT
Many thanks for the answers about inspect.signature. Using that, my new version of print_my_arg()
is:
from inspect import signature
def print_my_arg ( func, *args, **kwargs ):
func ( *args, **kwargs )
sig = signature ( func )
if 'my_arg' not in sig.parameters: return
binding = sig.bind ( *args, **kwargs )
binding.apply_defaults ()
print ( " my_arg = {}".format ( binding.arguments [ 'my_arg' ] ) )