Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forced naming of parameters in Python

In Python you may have a function definition:

def info(object, spacing=10, collapse=1)

which could be called in any of the following ways:

info(odbchelper)                    
info(odbchelper, 12)                
info(odbchelper, collapse=0)        
info(spacing=15, object=odbchelper)

thanks to Python's allowing of any-order arguments, so long as they're named.

The problem we're having is as some of our larger functions grow, people might be adding parameters between spacing and collapse, meaning that the wrong values may be going to parameters that aren't named. In addition sometimes it's not always clear as to what needs to go in. We're after a way to force people to name certain parameters - not just a coding standard, but ideally a flag or pydev plugin?

so that in the above 4 examples, only the last would pass the check as all the parameters are named.

Odds are we'll only turn it on for certain functions, but any suggestions as to how to implement this - or if it's even possible would be appreciated.

like image 497
Mark Mayo Avatar asked Oct 05 '22 08:10

Mark Mayo


People also ask

How do you force keyword arguments in Python?

A solution for this is to enforce using keyword arguments. This is possible to do in Python 2 by specifying a keyword argument dictionary, typically called **kwargs . However, in Python 3, there is a simple way to enforce it! By adding a * in the function arguments, we force all succeeding arguments to be named.

What are named parameters in Python?

Parameters are the input variables bounded by parentheses when defining a function, whereas arguments are the values assigned to these parameters when passed into a function (or method) during a function call.

What are the 4 types of arguments in Python?

5 Types of Arguments in Python Function Definition:positional arguments. arbitrary positional arguments. arbitrary keyword arguments.

Does Python allow default values for parameters?

Python allows function arguments to have default values. If the function is called without the argument, the argument gets its default value.


2 Answers

In Python 3 - Yes, you can specify * in the argument list.

From docs:

Parameters after “*” or “*identifier” are keyword-only parameters and may only be passed used keyword arguments.

>>> def foo(pos, *, forcenamed):
...   print(pos, forcenamed)
... 
>>> foo(pos=10, forcenamed=20)
10 20
>>> foo(10, forcenamed=20)
10 20
>>> foo(10, 20)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes exactly 1 positional argument (2 given)

This can also be combined with **kwargs:

def foo(pos, *, forcenamed, **kwargs):

To complete example:

def foo(pos, *, forcenamed ):
    print(pos, forcenamed)

foo(pos=10, forcenamed=20)
foo(10, forcenamed=20)
# basically you always have to give the value!
foo(10)

output:

Traceback (most recent call last):
  File "/Users/brando/anaconda3/envs/metalearning/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3444, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-12-ab74191b3e9e>", line 7, in <module>
    foo(10)
TypeError: foo() missing 1 required keyword-only argument: 'forcenamed'

So you are forced to always give the value. If you don't call it you don't have to do anything else named argument forced.

like image 324
Eli Bendersky Avatar answered Oct 07 '22 22:10

Eli Bendersky


You can force people to use keyword arguments in Python3 by defining a function in the following way.

def foo(*, arg0="default0", arg1="default1", arg2="default2"):
    pass

By making the first argument a positional argument with no name you force everyone who calls the function to use the keyword arguments which is what I think you were asking about. In Python2 the only way to do this is to define a function like this

def foo(**kwargs):
    pass

That'll force the caller to use kwargs but this isn't that great of a solution as you'd then have to put a check to only accept the argument that you need.

like image 58
martega Avatar answered Oct 07 '22 20:10

martega