[issue12192] Doc that collection mutation methods return item or None
New submission from Terry J. Reedy <tjreedy@udel.edu>: BACKGROUND One of most common recurring topics on python-list (perhaps monthly) is newbies tripping over a mutation method returning None when they expect the collection. Today's example: "Puzzled by list-appending behavior". An excerpt from the responses: "On 5/26/2011 11:58 AM, MRAB wrote:
On 26/05/2011 06:17, Chris Rebert wrote:
list.remove(), list.sort(), and list.extend() similarly return None rather than the now-modified list.
I'd just like to point out that it's a convention, not a rigid rule. Sometimes it's not followed, for example, dict.setdefault."
In Python 1, I believe it was true that all mutation methods of mutable builtin collections (ie, lists -- I do not think dicts had any and sets did not exist yet) returned None. With the introduction of list.pop, the return-None rule was 'broken', though the meme continues. However, the flip side of that rule, do-not-return-the-collection, continues to be true. And the return_None rule was not really broken, but broadened to "return None or an item from the collection". I believe this should be better documented than it is now. PROPOSALS 1. State the general rule. A. Tutorial: At the top of chapter 5, just after "This chapter describes some things you’ve learned about already in more detail, and adds some new things as well.", add something like "For lists, sets, and dicts, methods that change the contents or order never return the instance. Instead, they return an item from the instance or, more commonly, None." B. Library Manual: Near the top of 4. Built-in Types, after "The principal built-in types are numerics, sequences, mappings, classes, instances and exceptions.", add something like "Some collection classes are mutable. The methods that add, subtract, or rearrange their members never return the collection instance itself but instead return an item from the instance or None." Comment: This rule applies to special methods like __getitem__ and __setitem__. 'lis.append(item)' is equivalent to lis.__setitem__(len(lis):len(lis), item), so it should not be so surprising that it has the same return. 2. Document None returns explicitly. They are currently documented implicitly, by absence. A. Docstrings: Compare the relevant parts of the output from 'help(list.append)' and 'help(list.pop)' L.append(object) -- append object to end L.pop([index]) -> item -- remove and return item at index Add ' -> None' to specify return for .append. L.append(object) -> None -- append object to end I expect experienced Python programmers may object that this puts too much emphasis on the unimportant null return, but it is important that Python programmers know about it and experience shows that many newbies *need* that emphasis. B. Doc entries: Essentially same suggestion -- add 'Return None.' to appropriate entries in tutorial chapter 5. For library manual, possibly add footnote '(9) Returns None' to the method table in 4.6.4. Mutable Sequence Types. For sets and dicts, add 'and return None' to appropriate entries. ---------- assignee: docs@python components: Documentation messages: 137009 nosy: docs@python, terry.reedy priority: normal severity: normal status: open title: Doc that collection mutation methods return item or None versions: Python 2.7, Python 3.2, Python 3.3 _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue12192> _______________________________________
Changes by Chris Rebert <pybugs@rebertia.com>: ---------- nosy: +cvrebert _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue12192> _______________________________________
Raymond Hettinger <raymond.hettinger@gmail.com> added the comment: +1 on the doc suggestions -1 on any hope that casual users will have read or remembered them. ISTM that a common theme among the post of people getting tripped-up by this is that they aren't doing more than a quick skim of the docs anyway. ---------- nosy: +rhettinger _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue12192> _______________________________________
Ezio Melotti <ezio.melotti@gmail.com> added the comment: I find this wording a little confusing: "For lists, sets, and dicts, methods that change the contents or order never return the instance. Instead, they return an item from the instance or, more commonly, None.". I would suggest to drop the second part because we don't care about those methods now and because some of them return None too, and simply use "Methods that mutate the object never return the instance.", possibly adding something like "to remind you that no new objects have been created.". The same wording can be used in both the Tutorial and the Library Manual (if readers happen to read it twice, it's even more likely that they will remember it). FWIW the glossary has entries for "mutable" and "immutable", adding a note about this convention in the "mutable" entry might be a good idea too. Adding the '-> None' in the docstring is fine too, I'm not sure about the footnote. Terry, do you want to work on a patch? ---------- keywords: +easy nosy: +ezio.melotti stage: -> needs patch _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue12192> _______________________________________
Daniel Stutzbach <stutzbach@google.com> added the comment:
Comment: This rule applies to special methods like __getitem__ and __setitem__. 'lis.append(item)' is equivalent to lis.__setitem__(len(lis):len(lis), item), so it should not be so surprising that it has the same return.
It's not true for all special methods. __iadd__ and __imul__ return the list itself. That's a minor nitpick though. +1 on adding "and return None" to the docstrings of methods that often trip people up. Not everyone will read them, but some people will. ---------- nosy: +stutzbach _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue12192> _______________________________________
Terry J. Reedy <tjreedy@udel.edu> added the comment: Darn, I knew there might be an exception I was overlooking ;-). Anyway, I considered the general statements to be drafts, to be rewritten after comments. As to the footnote (9) suggestion: the set and dict sections list each method separately with normal entries, so there is not no problem with adding 'and returns None' to those that need it. The mutable sequence section is unique in instead putting all the methods in a condensed table. 'return None' could be added to some lines in the table, but not others. ---------- _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue12192> _______________________________________
Changes by Mike Hoy <mhoy09@gmail.com>: ---------- nosy: +mikehoy _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue12192> _______________________________________
Mike Hoy <mhoy09@gmail.com> added the comment: Created a patch based on suggestions here. ---------- keywords: +patch Added file: http://bugs.python.org/file23346/return-none.diff _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue12192> _______________________________________
Roundup Robot <devnull@psf.upfronthosting.co.za> added the comment: New changeset 352d075839f7 by Georg Brandl in branch 'default': Closes #12192: Document that mutating list methods do not return the instance (original patch by Mike Hoy). http://hg.python.org/cpython/rev/352d075839f7 ---------- nosy: +python-dev resolution: -> fixed stage: needs patch -> committed/rejected status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <http://bugs.python.org/issue12192> _______________________________________
participants (7)
-
Chris Rebert
-
Daniel Stutzbach
-
Ezio Melotti
-
Mike Hoy
-
Raymond Hettinger
-
Roundup Robot
-
Terry J. Reedy