Ian Kent
Ian Kent

Reputation: 791

Are Python args and kwargs ever named something else in practice?

Python does not restrict the names of parameters, however some parameter names are strongly governed by convention, such as self, cls, args, and kwargs. The names self and cls always represent the same concept, so in those cases it's hard for me to see a compelling reason for someone to veer from convention. With args and kwargs, however, I find this naming convention stifling.

Say I have a class that has various properties that can be set via passing kwargs to its constructor:

class MyObj:
    def __init__(self, **kwargs):
        for propname in kwargs:
            self.set_property(propname, kwargs[propname])

In this case, the kwargs are only intended to be settable properties of an instance of that class, so to me it would make sense to write the definition as follows:

class MyObj:
    def __init__(self, **properties):
        for propname in properties:
            self.set_property(propname, properties[propname])

That way, one only need look at the method's signature to get an idea of what the kwargs are for.

Generally, I believe convention is a good thing. However, it seems to me that always using args and kwargs is a missed opportunity to convey useful information to the user of an API about the nature of a function/method's args and kwargs. After all, the fact that they are unnamed or named arguments is already made clear by the presence of the single or double asterisk.

Does anyone have examples of alternate names for args and kwargs being used in real-world, multi-developer code or is it just too against the grain to use other variable names for these constructs?

If it really is just a horrible, horrible idea to not use these conventional names, what is the reason for that?

Upvotes: 5

Views: 1758

Answers (1)

timgeb
timgeb

Reputation: 78770

I don't see any reason against using context specific names, such as ...

my_sum(*numbers), my_parser(*strings, **flags), etc.

The print docs say *objects.

The zip docs say *iterables.

itertools.chain uses *iterables in the docs and in the docstring.

>>> from itertools import chain
>>> chain.__doc__.splitlines()[0]
'chain(*iterables) --> chain object'

collections.ChainMap uses *maps in the docs and in __init__.

>>> from collections import ChainMap
>>> from inspect import signature
>>> signature(ChainMap.__init__)
<Signature (self, *maps)>

Feel free to hunt for more examples.

Upvotes: 5

Related Questions