Meaning of "*args" not clear

In the documentation of Axes.plot, there is no indication of what “*args” means. If you search in the page for the string “*args”, there is only the one, first and sole, occurrence (in the formal parameters list itself).

It appears that “*args” is explained lower in the page, in the section labeled “Parameters.” But how might a new person know that for sure?

There are several ways to fix this, e.g., rename “Parameters” to “*args”, make “*args” a hyperlink to the “Parameters” section, etc.

I have seen this in many other pages (e.g., here, and similarly here) the feeling I have seen this same problem in many other doc pages. It is probably totally obvious to people who are used to matplotlob, but I am hoping and trying to exploit my newness to matplotlib to help uncover what appear to me might be some boiled frogs in the fundamental layout of the docs. In sum, it is very confusing to the newcomer to have a piece of documentation that says “the first argument is X” and then have zero occurrences of X anywhere on the page, and no links.

*args is the conventional way of writing a function with a variable number of positional arguements (the important thing is the *, args can be any valid Python identifier). While I appreciate that this can be confusing and we could spell this out in every docstring that uses *args, I am concerned that it would start to bloat the docstrings and make thing harder to read for other users.

We have to assume some level of Python knowledge on the part of our users and I think that it is reasonable to expect the reader to understand *args (just as we expect them to understand for-loops a bit further down in the plot docstring).

For better or worse, the signature of plot is very complicated (so that it can be easy to use!). The meaning of the first argument depends on if there is a second argument (and its type :scream: ) and it can take in infinite (well, very large) number of sequences of an optional x, y, and optional format string as positional formats. Hence, we can not write a nice clear signature at the top. The code block immediately below shows two parameterized ways of writing the signature and we are trying to illustrate the usage the examples just above Parameters.

I do not think we can rename the Parameters section as that name comes from numpydoc and I do not think that linking args to the Parameters section would be right (as the text between them is more explanatory of how to use the function).

I am very familiar with Python, and with Python documentation best practices, and with software documentation practices in general. I think it is safe to say that when someone very familiar with Python, or with API documentation in general, sees an entry in an API document for a function foo(*args), they expect the subsequent text to contain some mention of “args” or “*args.” It is normal if the text says, e.g., “args is the same thing as args in other_function” or “args is passed to other_function.” It is also normal, at least in some cases, if args is not spelled out explicitly, but its meaning is readily decipherable by a reasonable reader; for example, with max() it is obvious that args means arg3, arg4, etc.

But I do not think it is reasonable to expect a brand-new reader of the matplotlib documentation to understand instantly that when they see “*args” in a signature they should really search for “Parameters” in the subsequent text. It is confusing, and non-standard, and creates an unfortunate impression of low quality in what I know to be a fantastically high-quality tool.

You might be wondering: How would I know that matplotlib is high-quality, if I am so new to it? I should explain that. It was a bit misleading of me to say I am new to matplotlib. I have used it many times, but always in a hacky, one-off, cut-and-paste manner – just enough to draw some graph in the moment, and then move on. I have never dived deep into the documentation. When I say I am a newbie, I mean I am a newbie to really understanding framework – I am new to the matplotlib documentation. But I am familiar enough with matplotlib itself to know what a great tool it is.

Wouldn’t it be possible to post-process the output of numpydoc to rename Parameters to *args? (Actually, I can see that is not right – Parameters really is a section heading, and it would be better, perhaps, to adjoin “*args” just below it, for example.) If not that, I would like to understand better why linking “*args” to the Parameters section would be problematic. The former would be better, but either would be a huge improvement over the current state. (By the way, I did not understand the argument that “the text between them is more explanatory of how to use the function” at all. I’m not sure how that connects to this.)

Thank you for considering my input. I really appreciate your taking the time to respond.

I think that its reasonable that *args gets reused in the Parameters section, and then the entry under *args spells out the forms that *args should take, probably as a list?

That would be a nice solution, I think.

By the way, in looking back at my original post, I can TOTALLY see how it came off as my not knowing what “*args” meant, at the language level. I apologize for being so unclear! (I’m afraid I caused a lot of confusion.)

Python does not directly support overloaded signatures. You can only emulate them using variable parameters *args. While I would almost never introduce them today, we have a number of legacy cases we have to live with.

Sphinx shows this technical *args signature. I’d rather not have *args visible to the user at all, but that not something we can influence in the doc autogeneration of sphinx (and in particular we cannot replace it with multiple signatures).

The best solution we could come up with is the “Call signatures” block right below the summary line. Here, we can write down multiple signatures with the actual parameter names. This is what the user should look at not the formal *args signature. Can we make this more clear somehow, e.g. with better styling?
In plot this is really a bit dilluted by the following explanations. I think its already a bit better e.g. in tricontour.

IMHO putting *args in the parameters section is going the wrong direction. It’s putting emphasis on something the user should not know or care about.

Would some styling like this already help?

2 Likes

I still think that somewhere the meaning of *args should be explained. I think it’s incorrect to assume most Matplotlib users should know what this means before they can use the library. Yes it’s be better if this never appeared but sphinx aside, this shows up in every IDE that folks might use…

I do like the plot sig section above.

1 Like
  1. I believe overloading is non-Pythonic and should be avoided. Python functions have one signature; it is a fundamental characteristic of the language. The way to implement, and describe, the variation in usage for a given function, in Python, is via *args and **kwargs. It is misleading, especially to people who may be new to Python, to promote the idea that Python has function overloading natively.

  2. I believe the issue I originally raised is not as deep as this conversation is making it out to be. It is really a superficial problem of undefined references. Most people would agree that, if some documentation (any documentation, in any language) purports to explain some function foo(x), then the token x must appear lower down on the same page. In particular, if one searches from the top of the page for x, one expects to find at least two occurrences of x: the first one, inside the parentheses of foo(x), where x is introduced but not defined, and at least one other, defining x or providing a reference to its definition, lower on the page. If that is not a bedrock principle of API documentation (and of expository writing in general), I don’t know what is. The Axes.plot page violates this principle. (Note that it does not violate it with respect to **kwargs. If the documentation can follow the principle for **kwargs, it can follow it for *args.)

Another example where this principle is violated is pyplot.plot. Go to that page, activate the search function for whatever browser you are using, and type in “*args”. You will hit the “*args” that appears between the parenthesis surrounding the function’s formal parameter list at the top of the page. If you search again, you get nothing. That’s a doc bug.

One solution for this is to replace the non-Pythonic text “Call signatures” with the text “Admissible uses of *args:” or simply “How to use *args:”. I think that would solve the problem. 1) It eliminates undefined terms; 2) it fixes the problem of misleading readers into thinking Python is a language that has function overloading in the sense they may be used to in other languages; and 3) it is simple.