Proposal: don't nest optional brackets
To show a series of optional parameters, currently we nest square brackets. http://docs.python.org/dev/library/warnings.html#warnings.filterwarnings warnings.filterwarnings(action[, message[, category[, module[, lineno[, append]]]]]) My proposal is that we drop the nesting and write this as: warnings.filterwarnings(action [, message, category, module, lineno, append]) Currently the stylesheets make the brackets very big and dark, so I've also added a space before the bracket. This change means we'd lose the ability to show when two optional arguments must be supplied at the same time, which could currently be written like this: warnings.filterwarnings(action[, message, category[, module]]) In this hypothetical example, if you supply 'message' you must also supply 'category'. But I think that for most functions, you can supply each optional argument or not; you rarely need to supply two optional arguments that are tied in this way, and we can handle such cases by adding a sentence such as "Both message and category parameters must be supplied." A few places (difflib, doctest, probably others) use this format: .. function:: context_diff(a, b[, fromfile][, tofile][, fromfiledate][, tofiledate][, n][, lineterm]) It's better than the nested version -- at least it avoids the ]]]]]) at the end -- but I think having a single set of square brackets also works and reduces the symbolic noise further. .. function:: context_diff(a, b [, fromfile, tofile, fromfiledate, tofiledate, n, lineterm]) The brackets are large enough that I think this would still be quite readable; it doesn't seem likely that readers will miss that these parameters are optional. What does everyone think? --amk
On 20/06/2008, A.M. Kuchling <amk@amk.ca> wrote:
My proposal is that we drop the nesting and write this as:
warnings.filterwarnings(action [, message, category, module, lineno, append]) [...] What does everyone think?
Sounds OK to me - this is documentation, not a formal spec, so readability is more important than absolute precision. I wonder - what do other projects do? Consistency with common practice is likely to help readability, as well. Paul.
A.M. Kuchling schrieb:
To show a series of optional parameters, currently we nest square brackets.
http://docs.python.org/dev/library/warnings.html#warnings.filterwarnings
warnings.filterwarnings(action[, message[, category[, module[, lineno[, append]]]]])
My proposal is that we drop the nesting and write this as:
warnings.filterwarnings(action [, message, category, module, lineno, append])
Currently the stylesheets make the brackets very big and dark, so I've also added a space before the bracket.
Which will be ignored by the signature parser :)
This change means we'd lose the ability to show when two optional arguments must be supplied at the same time, which could currently be written like this:
warnings.filterwarnings(action[, message, category[, module]])
In this hypothetical example, if you supply 'message' you must also supply 'category'. But I think that for most functions, you can supply each optional argument or not; you rarely need to supply two optional arguments that are tied in this way, and we can handle such cases by adding a sentence such as "Both message and category parameters must be supplied."
That's reasonable. I can't remember if there's a function like this anywhere (with only the signature as a sign of this calling requirement).
A few places (difflib, doctest, probably others) use this format:
... function:: context_diff(a, b[, fromfile][, tofile][, fromfiledate][, tofiledate][, n][, lineterm])
It's better than the nested version -- at least it avoids the ]]]]]) at the end -- but I think having a single set of square brackets also works and reduces the symbolic noise further.
... function:: context_diff(a, b [, fromfile, tofile, fromfiledate, tofiledate, n, lineterm])
The brackets are large enough that I think this would still be quite readable; it doesn't seem likely that readers will miss that these parameters are optional.
What does everyone think?
I'm +0. I'd like to hear Fred's opinion since (I guess) he introduced the nested bracket notation. If he's okay with it, I'll write a script that converts the signatures in the whole documentation. cheers, Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.
Georg Brandl wrote:
A.M. Kuchling schrieb:
To show a series of optional parameters, currently we nest square brackets.
http://docs.python.org/dev/library/warnings.html#warnings.filterwarnings
warnings.filterwarnings(action[, message[, category[, module[, lineno[, append]]]]])
My proposal is that we drop the nesting and write this as:
warnings.filterwarnings(action [, message, category, module, lineno, append]) [...] What does everyone think?
I'm +0. I'd like to hear Fred's opinion since (I guess) he introduced the nested bracket notation. If he's okay with it, I'll write a script that converts the signatures in the whole documentation.
The nested bracket notation has been around for a very long time. It is used primarily to indicate positional arguments, any of which may logically be omitted, but all those to the left of the desired argument must be specified because of the positional nature of the arguments. Of course, the Pythonic thing is to specify just the desired arguments as keyword arguments and allow the rest to assume their defaults. I think that the strict notation to express this might be something like warnings.filterwarnings(action[, message=][, category=][, module=][, lineno=][, append]) but perhaps warnings.filterwarnings(action[, message, category, module, lineno, append]) is understood in a Python context to mean the same thing. +0 -- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan
[Just noticed this old conversation.] On Jun 22, 2008, at 7:36 AM, Georg Brandl wrote:
I'm +0. I'd like to hear Fred's opinion since (I guess) he introduced the nested bracket notation. If he's okay with it, I'll write a script that converts the signatures in the whole documentation.
Hmm. I'm fairly certain I didn't create it, but at this point, I might be mistaken. The nested notation makes sense for optional arguments, especially where keywords aren't supported. This is still the case for many of the APIs written in C, and those cases often won't be changed due to performance considerations. (Adding keyword support definitely slows things down.) For code implemented in Python, it's less of an issue, since the keyword support is always there unless the author of the code went out of the way to avoid it (using *args, for example). This happens, but isn't very common. But that's part of my reservation about this. With the nested notation, it's possible to specify signatures that are different from the implementation signatures. I think that's valuable still. So I guess now someone will tell me this has already been changed, and I missed it. --sigh-- -Fred -- Fred Drake <fdrake at acm.org>
On Tue, Sep 16, 2008 at 07:10:59PM -0400, Fred Drake wrote:
The nested notation makes sense for optional arguments, especially where keywords aren't supported. This is still the case for many of the APIs written in C, and those cases often won't be changed due to performance considerations. (Adding keyword support definitely slows things down.)
So, the use cases are: * Python code where arguments are both optional and specifiable as a keyword argument. * C code where keywords are supported. * C code where keywords are not supported. I think nesting the optional arguments doesn't actually indicate whether keywords are supported or not. For example, two functions from the socket module are: .. function:: getaddrinfo(host, port[, family[, socktype[, proto[, flags]]]]) .. method:: socket.recv_into(buffer[, nbytes[, flags]]) getaddrinfo() doesn't support keyword arguments; recv_into() does. But nesting the brackets does add a lot of typographical fluff. Can we invent a new notation for separating which functions support keywords and which don't? How would we render that distinction typographically in the output? Ideas: * Boldface parameters that can be provided as keywords. * Add '=' after parameters that can be provided as keywords: buffer=, [nbytes=, flags=] ... * Write keyword arguments as unnested square brackets: (buffer[, nbytes][, flags]) This reserves the nesting for functions that don't support keywords. I think the difflib docs are mostly written in this style.
So I guess now someone will tell me this has already been changed, and I missed it.
No, no one's made any changes relating to this yet. --amk
2008/9/24 A.M. Kuchling <amk@amk.ca>:
On Tue, Sep 16, 2008 at 07:10:59PM -0400, Fred Drake wrote:
I think nesting the optional arguments doesn't actually indicate whether keywords are supported or not. For example, two functions from the socket module are:
.. function:: getaddrinfo(host, port[, family[, socktype[, proto[, flags]]]]) .. method:: socket.recv_into(buffer[, nbytes[, flags]])
getaddrinfo() doesn't support keyword arguments; recv_into() does. But nesting the brackets does add a lot of typographical fluff.
Can we invent a new notation for separating which functions support keywords and which don't? How would we render that distinction typographically in the output?
I would like to suggest an idea which wouldn't involve typographical changes. I think keyword arguments could be represented just if they were in a dictionary, something like: buffer, **{nbytes, flags} Maybe it would take some time for the people to get used to the new syntax, but I think is it, at least, similar to Python code.
A.M. Kuchling schrieb:
To show a series of optional parameters, currently we nest square brackets.
http://docs.python.org/dev/library/warnings.html#warnings.filterwarnings
warnings.filterwarnings(action[, message[, category[, module[, lineno[, append]]]]])
My proposal is that we drop the nesting and write this as:
warnings.filterwarnings(action [, message, category, module, lineno, append])
Currently the stylesheets make the brackets very big and dark, so I've also added a space before the bracket.
This change means we'd lose the ability to show when two optional arguments must be supplied at the same time, which could currently be written like this:
warnings.filterwarnings(action[, message, category[, module]])
What does everyone think?
My proposal: Since we already give a Python-like signature, why not give the full signature for Python functions? That is, simply show default values for arguments like warnings.filterwarnings(action, message="", category=Warning, module="", lineno=0, append=0) That way, we also can get rid of awkward tons of parenthetical remarks like in "If foo is None (which is the default)", and also get to add that information in the first place where it was missing before. The argument defaults can be shown in a different typographical style if desired. Parameters whose default isn't easily displayable can continue to use the brackets. For C module functions that don't support keyword arguments, the old way of nested brackets precisely represents how to call the function, so it should stay. Sadly, this proposal is also the most work-intensive one since no automatic conversion is possible. This being the docs, it is however possible to tackle this over time on a per-module basis, so this is not necessarily a killer argument. Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out.
Georg Brandl wrote:
A.M. Kuchling schrieb:
To show a series of optional parameters, currently we nest square brackets.
http://docs.python.org/dev/library/warnings.html#warnings.filterwarnings
warnings.filterwarnings(action[, message[, category[, module[, lineno[, append]]]]])
My proposal is that we drop the nesting and write this as:
warnings.filterwarnings(action [, message, category, module, lineno, append])
Currently the stylesheets make the brackets very big and dark, so I've also added a space before the bracket.
This change means we'd lose the ability to show when two optional arguments must be supplied at the same time, which could currently be written like this:
warnings.filterwarnings(action[, message, category[, module]])
What does everyone think?
My proposal: Since we already give a Python-like signature, why not give the full signature for Python functions? That is, simply show default values for arguments like
warnings.filterwarnings(action, message="", category=Warning, module="", lineno=0, append=0)
That way, we also can get rid of awkward tons of parenthetical remarks like in "If foo is None (which is the default)", and also get to add that information in the first place where it was missing before.
The argument defaults can be shown in a different typographical style if desired. Parameters whose default isn't easily displayable can continue to use the brackets.
For C module functions that don't support keyword arguments, the old way of nested brackets precisely represents how to call the function, so it should stay.
Sadly, this proposal is also the most work-intensive one since no automatic conversion is possible. This being the docs, it is however possible to tackle this over time on a per-module basis, so this is not necessarily a killer argument.
+1 It is the most easily understood format by Python programmers for obvious reasons. Actually static code analysis should be able to automate this (or even live introspection). Michael
Georg
-- http://www.ironpythoninaction.com/ http://www.voidspace.org.uk/ http://www.trypython.org/ http://www.ironpython.info/ http://www.theotherdelia.co.uk/ http://www.resolverhacks.net/
Georg Brandl wrote:
My proposal: Since we already give a Python-like signature, why not give the full signature for Python functions? That is, simply show default values for arguments like
warnings.filterwarnings(action, message="", category=Warning, module="", lineno=0, append=0)
That way, we also can get rid of awkward tons of parenthetical remarks like in "If foo is None (which is the default)", and also get to add that information in the first place where it was missing before.
The argument defaults can be shown in a different typographical style if desired. Parameters whose default isn't easily displayable can continue to use the brackets.
I think that would be fine. Maybe a separate section can be added on the topic of understanding function arguments that uses the nested bracketed forms to help users understand python signatures. I was hoping at some point we might be able to generate the signatures and summary automatically from the source, and merge in the discussion and examples. But currently generating signatures isn't possible for all functions. BTW... Have you tried out the pydoc patch I submitted George? I haven't got any feedback on it yet, so it's just sitting there gathering dust. http://bugs.python.org/issue2001 Ron
For C module functions that don't support keyword arguments, the old way of nested brackets precisely represents how to call the function, so it should stay.
Sadly, this proposal is also the most work-intensive one since no automatic conversion is possible. This being the docs, it is however possible to tackle this over time on a per-module basis, so this is not necessarily a killer argument.
Georg
participants (8)
-
A.M. Kuchling -
Cristina Yenyxe González García -
Fred Drake -
Georg Brandl -
Mark Sapiro -
Michael Foord -
Paul Moore -
Ron Adam