Forced Naming of Parameters in Python

Forced naming of parameters in Python

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.

What is the purpose of default arguments for forced keyword arguments in Python?

It doesn't force you to provide the arguments, but it forces you to explicitly provide the keyword argument name when passing it. So function(1, 2, 3) won't work because you have to specify arg3 explicitly, i.e. function(1, 2, arg3=3). Apart from that, the behavior stays the same.

It is commonly used, when the developer realizes that without explicitly stating the name of the keyword argument for the given function can/will confuse the developer who reads the code later.

Variable name to be assigned as argument in a python function

Python functions generally don't "assign variable names", they just return values, and you can do whatever you want with those values.

A value doesn't have a variable name.* Because a value can be stored in five different variables, or it can be stored in things that aren't variables, like the elements of a list. It doesn't care.

So, what you almost certainly want to do is what @spectras suggested in a comment: Get rid of that first parameter, and then store the value in whatever variable you want:

def make_special_tree(arg1, arg2):
tree = Tree()
other_stuff = things(arg1)
modify_tree(tree, other_stuff, arg2)
return tree

# Two different trees with different names
blah = make_special_tree(foo, bar)
yoink = make_special_tree(foo, bar)

# One tree with two names
spam = make_special_tree(foo, bar)
eggs = spam

# A tree with no names at all
cheese = []
cheese.append(make_special_tree(foo, bar))

If you really do want to create a global variable with a specified name, you can do that,** but it's a really bad idea, unless you're trying to do something unusual, like the way collections.namedtuple acts like a class statement.


* A value can have a name by having, e.g., a name attribute. You can even change the definition of the Tree class to use that name attribute as part of its output representation. But this still has nothing to do with what variables you store it in.

** The least hacky way is globals()[name] = value.

Python Decorator to force passing arguments explicitly

If you can modify the function definition, refer to this question.

A minimal decorator to patch existing functions looks like this:

def explicitarguments(f):
def f_new(**kwargs):
return f(**kwargs)
return f_new

What are the conventions for ordering parameters in Python?

There's really no convention for ordering function parameters, except a limitation that positional non-default parameters must go before parameters with defaults and only then keyword parameters, i.e. def func(pos_1, pos_n, pos_1_w_default='default_val', pos_n_w_default='default_val', *args, kw_1, kw_n, kw_1_w_default='default_val', kw_n_w_default='default_val', **kwargs).

Usually you define parameters order logically based on their meaning for the function, e.g. if you define a function that does subtraction, it's logical, that minuend should be the first parameter and subtrahend should be second. In this case reverse order is possible, but it's not logical.

Also, if you consider that your function might be used partially, that might affect your decision on parameter ordering.

Most things you need to know about function parameters are in the official tutorial.

P.S. Regarding your particular example with graph function... Considering your function name, it is used for displaying a graph, so a graph must be provided as argument, otherwise there's nothing to display, so making graph=None by default doesn't make much sense.

Getting list of parameter names inside python function

Well we don't actually need inspect here.

>>> func = lambda x, y: (x, y)
>>>
>>> func.__code__.co_argcount
2
>>> func.__code__.co_varnames
('x', 'y')
>>>
>>> def func2(x,y=3):
... print(func2.__code__.co_varnames)
... pass # Other things
...
>>> func2(3,3)
('x', 'y')
>>>
>>> func2.__defaults__
(3,)

For Python 2.5 and older, use func_code instead of __code__, and func_defaults instead of __defaults__.

Naming parameters the same as the variable passed to them?

The "problem" in this particular case is that the function parameter name will shadow the outer param variable; i.e. you cannot (implicitly) refer to the global param anymore because inside your function param is defined as a local variable.

But, this is really as it should be. Your function should only worry about the parameters it declares locally, not about implicit global variables. Conversely, a caller of a function should not have to worry about anything that goes on inside a function. Naming a variable the same as a parameter to a function is of no consequence to the caller, and should be of no consequence to the function itself.

So, no, there's absolutely no issue here.



Related Topics



Leave a reply



Submit