Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count how many arguments passed as positional

If I have a function

def foo(x, y):     pass 

how can I tell, from inside the function, whether y was passed positionally or with its keyword?

I'd like to have something like

def foo(x, y):     if passed_positionally(y):         print('y was passed positionally!')     else:         print('y was passed with its keyword') 

so that I get

>>> foo(3, 4) y was passed positionally >>> foo(3, y=4) y was passed with its keyword 

I realise I didn't originally specify this, but is it possible to do this whilst preserving type annotations? The top answer so far suggests using a decorator - however, that does not preserve the return type

like image 435
ignoring_gravity Avatar asked May 21 '21 14:05

ignoring_gravity


People also ask

How do you determine the number of passing arguments?

You can get the number of arguments from the special parameter $# . Value of 0 means "no arguments". $# is read-only. When used in conjunction with shift for argument processing, the special parameter $# is decremented each time Bash Builtin shift is executed.

How many positional parameters are there?

The command line has three parameters: one, two, and three four. Positional parameters are delimited by a space. The shell interprets the things after the spaces as individual parameters. If the parameter itself contains a space, enclose it in quotation marks, as in "three four," above.

How many arguments can be passed to make?

Any number of arguments can be passed to a function. There is no limit on this. Function arguments are stored in stack memory rather than heap memory.

How many arguments are passed in main () function?

The main() function has two arguments that traditionally are called argc and argv and return a signed integer.


1 Answers

You can create a decorator, like this:

def checkargs(func):     def inner(*args, **kwargs):         if 'y' in kwargs:             print('y passed with its keyword!')         else:             print('y passed positionally.')         result = func(*args, **kwargs)         return result     return inner  >>>  @checkargs ...: def foo(x, y): ...:     return x + y  >>> foo(2, 3) y passed positionally. 5  >>> foo(2, y=3) y passed with its keyword! 5 

Of course you can improve this by allowing the decorator to accept arguments. Thus you can pass the parameter you want to check for. Which would be something like this:

def checkargs(param_to_check):     def inner(func):         def wrapper(*args, **kwargs):             if param_to_check in kwargs:                 print('y passed with its keyword!')             else:                 print('y passed positionally.')             result = func(*args, **kwargs)             return result         return wrapper     return inner  >>>  @checkargs(param_to_check='y') ...: def foo(x, y): ...:     return x + y  >>> foo(2, y=3) y passed with its keyword! 5 

I think adding functools.wraps would preserve the annotations, following version also allows to perform the check over all arguments (using inspect):

from functools import wraps import inspect  def checkargs(func):     @wraps(func)     def inner(*args, **kwargs):         for param in inspect.signature(func).parameters:             if param in kwargs:                 print(param, 'passed with its keyword!')             else:                 print(param, 'passed positionally.')         result = func(*args, **kwargs)         return result     return inner  >>>  @checkargs ...: def foo(x, y, z) -> int: ...:     return x + y  >>> foo(2, 3, z=4) x passed positionally. y passed positionally. z passed with its keyword! 9  >>> inspect.getfullargspec(foo) FullArgSpec(args=[], varargs='args', varkw='kwargs', defaults=None,  kwonlyargs=[], kwonlydefaults=None, annotations={'return': <class 'int'>})                                              _____________HERE____________ 
like image 194
Sayandip Dutta Avatar answered Oct 06 '22 06:10

Sayandip Dutta