This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: return value of builtins is not clearly indicated
Type: Stage: patch review
Components: Documentation Versions: Python 3.11
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: SnoopJeDi, barry, docs@python, eric.araujo, iritkatriel, nedbat, steven.daprano, terry.reedy
Priority: normal Keywords: patch

Created on 2022-01-06 14:52 by SnoopJeDi, last changed 2022-04-11 14:59 by admin.

Pull Requests
URL Status Linked Edit
PR 30435 closed SnoopJeDi, 2022-01-06 14:53
Messages (17)
msg409857 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2022-01-06 15:14
Do the print docs need to mention something so obvious?

Functions and methods which operate by side-effect typically don't mention that they return None, see for example the docs for various builtin methods:

https://docs.python.org/3/library/stdtypes.html#mutable-sequence-types

e.g. s.append, s.clear, s.extend, s.insert, s.remove, s.reverse

and likewise for list.sort, set.add, dict.clear and many others.

(However, dict.update is a rare exception, it does mention that it returns None.)

We should not feel it necessary to add an explicit comment to every function or method that operates by side-effect stating that they return None.
msg409870 - (view) Author: James Gerity (SnoopJeDi) Date: 2022-01-06 16:13
I opened this ticket on behalf of a user who asked about print() specifically in #python on the Libera IRC network, who I assume does not find this obvious.

I don't think it would be tenable to add this note to every built-in, but that's not the intended scope of this issue. I do think it's worth mentioning for print(), though.
msg409874 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2022-01-06 16:40
I think it does a better service to users to explain how Python returns None implicitly if a function doesn't have any other explicit return value.  If the print() docs had this note, it would be confusing why other similar functions don't.

It's also worth explaining that when a function is designed to *explicitly* return None in certain cases (e.g. dict.get()) that it shouldn't do so implicitly, but should include an explicit `return None` for readability.
msg409883 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2022-01-06 17:15
Sure, there will always be some users who will find certain things not 
obvious. Sometimes I'm that user myself.

What did this user think print() returned? What precisely was their 
question? Perhaps if I saw the conversation in context, I would be more 
sympathetic to this.

I can see a difference between (for example) the questions:

"I see that print('Hello world') returns None, but is it safe to assume 
that print will *always* return None? It is not documented anywhere as 
far as I can see."

and

"What does x = print('Hello world') do?"
msg409886 - (view) Author: James Gerity (SnoopJeDi) Date: 2022-01-06 17:26
The original question was closer to the related issue of "indicate return types for all built-ins," conversation log follows (UTC-5):

```
09:33:50         ringo__ | is there a stdlib api docs which actually has *full* functions signature?                                                                                                       
09:34:27         ringo__ | for example, https://docs.python.org/3/library/functions.html, function                                                                                                         
                         | abs(x), it returns what, int? I need to read the whole sentence to figure                                                                                                       
                         | out the return value of a function?                                                                                                                                             
09:34:48         ringo__ | (or argument for that matter)                                                                                                                                                   
09:35:51             bjs | ringo__: well like it says it doesn't just support int                                                                                                                          
09:36:00             bjs | int, float, or any type that supports it                                                                                                                                        
09:37:01             bjs | in general you can find actual type annotations for the functions in the                                                                                                        
                         | typeshed                                                                                                                                                                        
                         | https://github.com/python/typeshed/blob/master/stdlib/builtins.pyi                                                                                                              
09:37:32             bjs | I wonder if it would be useful to include the typeshed annotation in the                                                                                                        
                         | docs, or whether it would be more confusing                                                                                                                                     
09:37:49         ringo__ | Thanks bjs ! I'll bookmark this typeshed                                                                                                                                        
09:38:13          SnoopJ | abs() will do whatever __abs__() on the type does, which can be different                                                                                                       
                         | for any given type. You'd expect T -> T but it's not guaranteed.                                                                                                                
09:38:18         ringo__ | I used abs() as an example. In fact I was wondering what does print()                                                                                                           
                         | return. I *guessed* it returns None, but the docs won't say                                                                                                                     
09:39:05         ringo__ | I could do a try-it-yourself approach but I was puzzled why the docs                                                                                                            
                         | simply won't give you full fn signature, ie print(..) -> None                                                                                                                   
09:39:17          SnoopJ | that one is just an omission :)
```
msg410038 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2022-01-07 21:34
How about following "The Python interpreter has a number of functions and types built into it that are always available. They are listed here in alphabetical order." in
https://docs.python.org/3/library/functions.html
with "Here and elsewhere in these docs, entries for functions (including methods) that always return None usually omit 'Return None' and just say what the function does."

Barry: The PEP 8 'return None' recommendation could be added to the Reference entry for 'return'.  But I think this should be a separate issue as 1) it is about coding rather than documentation and 2) there is the possible objection that choosing completely explicit 'return None' versus half explicit, half implicit 'return' and the latter versus completely implicit <nothing at end> should be left to the style PEP.
msg410046 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2022-01-07 22:23
> Barry: The PEP 8 'return None' recommendation could be added to the Reference entry for 'return'.  But I think this should be a separate issue as 1) it is about coding rather than documentation and 2) there is the possible objection that choosing completely explicit 'return None' versus half explicit, half implicit 'return' and the latter versus completely implicit <nothing at end> should be left to the style PEP.

I do think it's a question of style.  Section 7.6 of the language reference says:

> If an expression list is present, it is evaluated, else None is substituted.

which is the important concept that beginners should learn.

I agree that the admonition in PEP 8 is really trying to say "don't mix implicit and explicit return styles".  Implicit None return is fine if all exit paths are implicit.  But once you add an explicit value to a return path, all return paths should use explicit values, including those that return None.

IME, while I do occasionally encounter push back on this when doing reviews, most folks come around to this p.o.v.
msg411632 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2022-01-25 16:58
The new title is puzzling; the discussion moved to advertising that all functions default to returning None, this is not related to the built-in status.
msg411653 - (view) Author: James Gerity (SnoopJeDi) Date: 2022-01-25 18:12
> advertising that all functions default to returning None

This is already communicated in § 4.7 ("Defining Functions") of the official tutorial. 

I think it would be a good idea to revise that section so that this property of functions is a little more clear, but that isn't the scope of this ticket.

The title change reflects my intent to submit a PR that adds a hint to the builtins doc.
msg411664 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2022-01-25 19:12
Please post your proposed change here to be discussed by participants here.
msg411668 - (view) Author: James Gerity (SnoopJeDi) Date: 2022-01-25 19:42
My thought was to add something like this to the top of functions.rst:

```
Note that some of the functions listed here have the :ref:`default return value <tut-defining-functions> of ``None``.
```

For reference, the builtins this applies to are:

* breakpoint()
* delattr()
* exec()
* help()
* print()
* setattr()

Which makes me wonder if the hint is even worth having, since it's so few of them.

Note that of these, exec() does what this ticket originally proposed for print() - i.e. it explicitly says that the function returns None.
msg411809 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2022-01-26 23:35
> "have the :ref:`default return value <tut-defining-functions> of ``None``."


This sounds to me like "by default they return None but you can override this default".

I don't think any change to the doc makes sense here. When you state the obvious people wonder what they're missing.
msg411835 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2022-01-27 04:00
Steven, I am also inclined to close this.  What do you think after the discussion?  It is sometimes easier to clarify when we have a confused person present in the discussion.
msg412797 - (view) Author: Ned Batchelder (nedbat) * (Python triager) Date: 2022-02-07 22:39
> When you state the obvious...

Obvious to who? New learners coming to Python don't know the same things as people with experience.
msg412811 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2022-02-08 05:16
> New learners coming to Python don't know the same things
> as people with experience.

IMO, new learners will be worse off by adding "returns None" to all of the builtins.  At best it a distractor.

I work with new learners almost every day.  The issue never arises.  No one writes "x = print('hello world')" and they would be worse off if shown such a possibility.

One other consideration is that MyPy and the tools that use it (such as PyCharm) reject the idea of None as return value.  Their view is that no value is returned all.  We don't want the docs to contradict that world view.

  $ cat hello.py
  x = print('hello world')
  $ mypy hello.py
  hello.py:1: error: "print" does not return a value
  Found 1 error in 1 file (checked 1 source file)
msg412836 - (view) Author: Ned Batchelder (nedbat) * (Python triager) Date: 2022-02-08 13:06
What we're debating here is a micro-cosm of the broader "documentation philosophy" questions that I'm hoping the Documentation WG can iron out.  

What is "obvious"? Is it obvious that print returns None when file.write does not? Why does "exec" explicitly say it returns None, and no beginners were harmed, but having "print" say it returns None would be bad?
msg412838 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2022-02-08 13:11
I should have said "redundant information" rather than "obvious". 

I consider it redundant to specify that the default behavior applies to some specific case. If I read redundant information I may pause to think why it was necessary to explicitly state it, and whether I am misunderstanding something.

(Let's not make my bad choice of word turn this into a discussion about "what is obvious". The issue will probably never be closed if we do that.)
History
Date User Action Args
2022-04-11 14:59:54adminsetgithub: 90440
2022-02-12 01:20:07rhettingersetnosy: - rhettinger
2022-02-08 13:11:46iritkatrielsetmessages: + msg412838
2022-02-08 13:06:19nedbatsetmessages: + msg412836
2022-02-08 05:16:47rhettingersetnosy: + rhettinger
messages: + msg412811
2022-02-07 22:39:55nedbatsetnosy: + nedbat
messages: + msg412797
2022-01-27 04:00:46terry.reedysetmessages: + msg411835
2022-01-26 23:35:50iritkatrielsetnosy: + iritkatriel
messages: + msg411809
2022-01-25 19:42:03SnoopJeDisetmessages: + msg411668
2022-01-25 19:12:19terry.reedysetmessages: + msg411664
2022-01-25 18:12:25SnoopJeDisetmessages: + msg411653
2022-01-25 16:58:10eric.araujosetmessages: + msg411632
2022-01-25 16:46:11SnoopJeDisettitle: print() docs do not indicate its return value -> return value of builtins is not clearly indicated
2022-01-07 22:23:15barrysetmessages: + msg410046
2022-01-07 21:34:03terry.reedysetnosy: + terry.reedy
messages: + msg410038
2022-01-07 18:48:35eric.araujosetnosy: + eric.araujo
2022-01-06 17:26:35SnoopJeDisetmessages: + msg409886
2022-01-06 17:15:13steven.dapranosetmessages: + msg409883
2022-01-06 16:40:33barrysetnosy: + barry
messages: + msg409874
2022-01-06 16:13:18SnoopJeDisetmessages: + msg409870
2022-01-06 15:14:42steven.dapranosetnosy: + steven.daprano
messages: + msg409857
2022-01-06 14:53:41SnoopJeDisetkeywords: + patch
stage: patch review
pull_requests: + pull_request28642
2022-01-06 14:52:27SnoopJeDicreate