Reputation: 791
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
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