Tell us how the argument was received by the function?

I would like to know if the following feature is possible in cpython:

>>> def potato(x=69): ... if x == 69 and ???: ... print '69 was taken from argument defaults' ... if x == 69 and ???: ... print '69 was passed as positional arg' ... if x == 69 and ???: ... print '69 was passed as kwarg' ... >>> potato() 69 was taken from argument defaults >>> potato(69) 69 was passed as positional arg >>> potato(x=69) 69 was passed as kwarg 

I am interested in both python2 and python3 answers if they are different.

Any kind of black wave, including inspect , traceback , pdb , sys._getframe , etc., is permissible here. Of course, changing a function argument is not allowed.

+6
source share
1 answer

It doesn't seem like validation can provide this information directly, although frames have a line called code_context, which gives you the source line in which the function was called. The problem is that you would need to rewrite a small parser to figure this out.

Here is a simpler solution based on a wrapper around the function you want to learn. It does not change the arg specification, and the validation of arg does not change either:

 import inspect def track_args(func): def tracker(*args, **kwargs): r = func(*args, **kwargs) for arg_num,arg_name in enumerate(inspect.getargspec(func)[0]): if arg_name in kwargs: print "%s was provided as keyword arg" % arg_name elif arg_num < len(args): print "%s was provided as positional arg" % arg_name else: print "%s was provided by default value" % arg_name return r return tracker @track_args def f(a, b, c=30): print "I'm f()" f(20, b=10) f(20) 

Result with valid arguments:

 I'm f() a was provided as positional arg b was provided as keyword arg c was provided by default value 

Result with invalid arguments:

 Traceback (most recent call last): File "test.py", line 21, in <module> f(20) File "test.py", line 5, in tracker r = func(*args, **kwargs) TypeError: f() takes at least 2 arguments (1 given) 
+1
source

All Articles