I've been looking at the source code for an open source package that I'm using. Nearly every function uses *args instead of named arguments. I'm finding it hard to follow and use the code, because every time I want to call a function I have to go back, pick through the source code, and identify what the arguments should be, and what order they should be in. The question I have is this: Is there a compelling reason to use *args in every function, or is this an abuse of the concept? Thanks, -b
-
If there's *args, there needs to be an (accurate!) docstring. – James Sep 19 '12 at 23:43
-
What package is it? Not to play the blame game, but they may have a valid reason. – Matthew Trevor Sep 20 '12 at 00:24
5 Answers
This might be a personal reasoning but I only use *args and **kwargs when I have a lot of optional fields where some fields are only used in a certain context.
The only other occasion I used args is when I was building an XML RPC client for a cloud API. Since I was just passing parameters to an underlying layer and since the function where generated dynamically, I had no other choices but to use *args as I had no way to know all the parameters in advance.
In most case, you won't even need it. I consider it to be mostly laziness than anything else.
Some people who comes from Java and C# might use this as a replacement for "params", but there are so many way to pass optional parameters in python.
And I agree that even if you use *args, you should have a very good documentation.

- 6,794
- 13
- 20
-
In two years of coding C# I've used `params` twice. In a month of Python, I've seen `(*args, **kwargs)` so many times that it makes my eyes bleed. I would recommend using it sparingly; it's a tool that should be used to solve a very specific problem. And as we know, when you give people a tool that's this easy to use, they will overuse and abuse it to no end. – Dagrooms Nov 16 '17 at 21:38
Using *args
in every function is a bad idea because it can mask errors in your code (calling a function with the wrong number of arguments). I suppose the rule of thumb should be to only use *args
if you need *args
.

- 300,191
- 65
- 633
- 696
In the Zen of Python, we are told to prefer explicit over implicit. Explicit arguments should be used whenever possible.

- 299,747
- 42
- 398
- 622
-
1@nneonneo Quoting from the Zen with no further commentary is pretty useless. The guidelines in the Zen of Python are great, but not just because they're in the Zen of Python, they're good ideas for *good reasons*. Memorising the Zen of Python without *understanding* the reasons for those guidelines (so you can recognise when departing from them) doesn't help you apply them well. – Ben Sep 20 '12 at 05:20
-
@Ben, I didn't think it was my place to speculate on why that particular item is in the Zen. In this case I thought it was pretty obvious - explicit is easier to understand and follow. I've also found that working with the same principles that guide your platform designer just makes things better overall, not just in Python. – Mark Ransom Sep 20 '12 at 14:29
When there's no compelling reason to use *args
, it's an abuse of the concept. Usually there are good names for arguments, which help comprehension. Even when there aren't, (x, y, z)
tells you more than (*args)
.
And beyond making code more readable, it also helps to catch errors (e.g., if you call a (x, y, z)
function with (2, 3)
you'll get an error at the call, rather than deep inside the function), it's usually more concise, and it can even be more efficient.
But there are sometimes compelling reasons for widespread use of *args
.
For example, if you're wrapping a lower-level (C or otherwise) module and want to do perfect forwarding, it's easier with *args
. Even more so if you're automatically generating the wrapper code rather than writing it manually. Of course this is still a tradeoff—it's much easier for the developer of the wrapper module, but more difficult for the users—but sometimes the tradeoff is worth taking.
Without knowing the particular package you're referring to, it's impossible to guess whether it's a compelling use case or an abuse.

- 354,177
- 51
- 601
- 671
If you're wrapping an unknown function (the functions returned by decorators often do this), then you often need to use (*args, **kwargs)
.
Some class hierarchies use (*args, **kwargs)
in methods that can need different signatures at different classes in the hierarchies (__init__
is a prime culprit). It's really helpful if you can avoid that, but can be necessary to work with multiple inheritance hierarchies in a sane manner (or as sane as is possible with multiple inheritance, at least).
I sometimes end up using **kwargs
when I have a large number of optional arguments, but this requires a lot of documentation.
In a function that's consuming the *args
itself (rather than passing them to some other function with an unknown signature, as in the decorator or class inheritance cases), then I tend to think that *args
should almost never be used except to mean "zero or more of the same kind of thing". And in that case you should be naming it *websites
or *spaceships
or *watermelons
, not *args
. A bunch of unrelated parameters shouldn't be squashed into *args
. Even worse would be for the function to use *args
to take "an x, a y, and a z, or else an x and a z", where the second parameter does different things depending on how many parameters are passed. At that point they should clearly all have names and defaults (even if it's just the standard None
default then see in the function which ones are non-None
pattern) and be passed by keyword rather than by position.

- 68,572
- 20
- 126
- 174