582

Consider these three functions:

def my_func1():
  print "Hello World"
  return None

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

They all appear to return None. Are there any differences between how the returned value of these functions behave? Are there any reasons to prefer one versus the other?


See also: is it possible to not return anything from a function in python?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Clay Wardell
  • 14,846
  • 13
  • 44
  • 65
  • 67
    Note that there's a stylistic difference. `return None` implies to me that the function sometimes has a non-`None` return value, but at the location of `return None`, there is no such return value. Writing no `return` at all implies to me there's never an interesting return value, kinda like a "procedure" as opposed to a "function". `return` implies to be existing early from a "procedure" as per the previous point. –  Mar 08 '13 at 18:19

5 Answers5

745

On the actual behavior, there is no difference. They all return None and that's it. However, there is a time and place for all of these. The following instructions are basically how the different methods should be used (or at least how I was taught they should be used), but they are not absolute rules so you can mix them up if you feel necessary to.

Using return None

This tells that the function is indeed meant to return a value for later use, and in this case it returns None. This value None can then be used elsewhere. return None is never used if there are no other possible return values from the function.

In the following example, we return person's mother if the person given is a human. If it's not a human, we return None since the person doesn't have a mother (let's suppose it's not an animal or something).

def get_mother(person):
    if is_human(person):
        return person.mother
    else:
        return None

Using return

This is used for the same reason as break in loops. The return value doesn't matter and you only want to exit the whole function. It's extremely useful in some places, even though you don't need it that often.

We've got 15 prisoners and we know one of them has a knife. We loop through each prisoner one by one to check if they have a knife. If we hit the person with a knife, we can just exit the function because we know there's only one knife and no reason the check rest of the prisoners. If we don't find the prisoner with a knife, we raise an alert. This could be done in many different ways and using return is probably not even the best way, but it's just an example to show how to use return for exiting a function.

def find_prisoner_with_knife(prisoners):
    for prisoner in prisoners:
        if "knife" in prisoner.items:
            prisoner.move_to_inquisition()
            return # no need to check rest of the prisoners nor raise an alert
    raise_alert()

Note: You should never do var = find_prisoner_with_knife(), since the return value is not meant to be caught.

Using no return at all

This will also return None, but that value is not meant to be used or caught. It simply means that the function ended successfully. It's basically the same as return in void functions in languages such as C++ or Java.

In the following example, we set person's mother's name and then the function exits after completing successfully.

def set_mother(person, mother):
    if is_human(person):
        person.mother = mother

Note: You should never do var = set_mother(my_person, my_mother), since the return value is not meant to be caught.

jshd
  • 187
  • 3
  • 9
  • 15
    `var = get_mother()` is OK if you're passing `var` to other functions that accept `None` - "never" is a little extreme – joel Nov 16 '18 at 12:15
  • How should one accept the return value if `var = get_mother()` can't be used? IMHO it's totally fine to do that. You just need to make sure to check for a non `None` value with `if var` before using it. – winklerrr Dec 10 '18 at 07:39
  • I thought it was important to mention that this is not just a good convention, it is required by PEP8. I post an answer to compliment yours and quote PEP8 on this. – Fabiano Dec 04 '19 at 23:42
  • Why should `return values` not be `caught`? – Artur Müller Romanov Jul 13 '20 at 08:47
  • If an answer gets another point on Stack Overflow, but no one is around to collect it, does it count as reputation? – mirekphd Aug 19 '21 at 16:49
  • @mirekphd you're right, technically it's not reputation anymore. But it's still useful for letting everyone else know how useful the answer has been. – Mark Ransom Nov 20 '22 at 23:06
51

Yes, they are all the same.

We can review the interpreted machine code to confirm that that they're all doing the exact same thing.

import dis

def f1():
  print "Hello World"
  return None

def f2():
  print "Hello World"
  return

def f3():
  print "Hello World"

dis.dis(f1)
    4   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    5   5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f2)
    9   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    10  5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f3)
    14  0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE            
        5 LOAD_CONST    0 (None)
        8 RETURN_VALUE      
David Marx
  • 8,172
  • 3
  • 45
  • 66
  • 8
    careful here... `dis.dis` returns `None` :-X – mgilson Mar 08 '13 at 18:23
  • The only way to get the output of dis as a string is to redirect stdout to some sort of IO buffer (e.g. StringIO). Even then, comparing directly like that might not work as I believe `dis.dis` also reports some line numbers ... – mgilson Mar 08 '13 at 18:28
  • It's irrelevant whether or not they're using the exact same registers anyway, so I changed my code so we've just look eyeballing the machine code now instead of doing some sort of goofy string comparison. Thanks for the very big heads up. – David Marx Mar 08 '13 at 18:31
  • @mgilson Nowadays one can also use [`dis.Bytecode.dis()`](https://docs.python.org/3/library/dis.html#dis.Bytecode.dis). – ruohola Sep 25 '20 at 13:54
26

They each return the same singleton None -- There is no functional difference.

I think that it is reasonably idiomatic to leave off the return statement unless you need it to break out of the function early (in which case a bare return is more common), or return something other than None. It also makes sense and seems to be idiomatic to write return None when it is in a function that has another path that returns something other than None. Writing return None out explicitly is a visual cue to the reader that there's another branch which returns something more interesting (and that calling code will probably need to handle both types of return values).

Often in Python, functions which return None are used like void functions in C -- Their purpose is generally to operate on the input arguments in place (unless you're using global data (shudders)). Returning None usually makes it more explicit that the arguments were mutated. This makes it a little more clear why it makes sense to leave off the return statement from a "language conventions" standpoint.

That said, if you're working in a code base that already has pre-set conventions around these things, I'd definitely follow suit to help the code base stay uniform...

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • 1
    Or more generally, any time a function ends without hitting a `return` statement, it returns `None`. –  Mar 08 '13 at 18:14
  • It's not idiomatic to omit the return statement if the function is expected to return a value. Only functions that operate solely through side effects should omit the return statement. – molecule Jun 09 '16 at 02:07
  • @molecule -- Yeah, I think that perhaps I didn't do the best job in my explanation here. I've tried to update it without making it a complete clone of the (much better) answer above. I'm still not super happy with this post... Part of me wants to delete it (since the answer above is so much better) and part of me wants to keep it -- 9 people so far have thought it was good for one reason or another. Maybe I hit on something someone else missed? – mgilson Jun 09 '16 at 02:27
  • Thanks. That's better. – molecule Jun 10 '16 at 11:58
  • Not returning a value is not idiomatically the same as returning None. It is a design flaw in python that it is not tracking if function return anything or not. If your function doesn't return anything and you still use its call in an expression it should signal error just like it does if you use an unassigned variable in expression. There should be no None by default. – ZAB Jan 11 '18 at 11:34
  • 1
    @ZAB -- I don't think that's possible. In python I can monkey patch anything with anything (this is by design and it's a great feature if used sparingly). Specifically, I can monkey-patch a function that has a return with one that doesn't. All of the "not an expression" checks happen at parse time, but due to monkey-patching, this couldn't happen until runtime. IOW, it's completely different. Personally, I think that the current behavior is quite reasonable (and consistent with other high-level languages), but I'm not the one you need to convince :-). – mgilson Jan 11 '18 at 13:40
  • @mgilson the use of uninitialized variable is exactly the same as using a function result it didn't return. Idiomatically. The first is checked by Python and the later is not. It masks errors. Most other high level languages not let you use a function that return say `void` in expression and also issue warnings and errors if you try to declare a function that don't return value on all its control paths. Actually most other languages are more rigorous when it comes to return values than variable initialization. – ZAB Jan 12 '18 at 16:20
  • 1
    @ZAB -- both `Ruby` and `Javascript` take the same approach as python. I'm sure that there _are_ examples of high level languages that say "void" in the expression but I can't think of any at the moment (maybe if you consider `Java` a high-level language) ... How would monkey-patching a function (which is useful for mocking in tests among other things) work in a hypothetical world where python got a `void` keyword that made it so the function didn't return anything? (Also, as I said before, you don't need to convince me that this is a bad design. I can't do anything even if you're right) – mgilson Jan 13 '18 at 15:36
  • @mgilson I am not talking about strongtyping. Just track if the function did return anything or ended up with blank return or a control flow just leaves its body. It is the same as tracking variable assignments. Variables aren't None by default, it raise an exception if you use unassigned variable in expression, so why do function result value is None by default? No sense. Yes javascipt also have this inconsistency in it, but javascript have never pretend to be safe language that is designed to prevent stupid errors in code, while python does. – ZAB Jan 14 '18 at 16:41
  • @ZAB I think returning `None` if there is no `return` is extremely sensible. What else would it return, except for nothing? `None` is the same concept as `nil`, or `void`, or `nothing`. It would be bad to implicitly return `0`, because that's an integer with a meaningful value. That's why `None` exists. – Greg Schmit Jan 15 '18 at 18:39
  • @GregSchmit it shouldn't return anything. And the result value shouldn't be used. You may call this function but not use its return value in expression if it wasn't explicitly provided. A similar behavior to void functions in C but there is no need in any new type actually. – ZAB Jan 15 '18 at 21:08
  • @ZAB Returning `None` is the same as returning `nothing`. `None` is `nothing`. That's the purpose of `None`, to communicate the idea of `nothing`. – Greg Schmit Jan 15 '18 at 22:09
  • 1
    @GregSchmit no. Assigning None to a variable is not the same as leaving it uninitialized. You can read None from a variable you can check it and use it in if condition but you can't read and use uninitialized variable, you'll get an exception. The same should be for a function return value. – ZAB Jan 15 '18 at 23:22
  • @ZAB I'm cleaning up the comments. I think we just have a disagreement about how the language should work. If you want to throw NameError for assigning a function that doesn't have an explicit return value, you'd have to do that at runtime vs parsetime like @mgilson mentioned, and I don't think it would do anything to make the language better. To me it seems totally normal to return `None` with no return statement, since you're not returning anything, and that's what `None` is for. – Greg Schmit Jan 16 '18 at 00:19
  • @ZAB Ruby must really frighten you! Since they return the result of the last line if you don't have a `return` statement. The horror! :) – Greg Schmit Jan 16 '18 at 00:20
  • @GregSchmit fortran is already frightening me for having arrays index started from 1. Would you defend it too? Languages have some imperfections. I don't know any perfect language. – ZAB Jan 16 '18 at 00:29
  • 1
    Also, `a = myfunc()` is initializing `a`, so throwing an uninitialized error would be meaningless. `None`'s whole job in life is to be the opposite of anything (any meaningful value), so when a function doesn't return anything, that's the same as returning `None`. – Greg Schmit Feb 03 '18 at 17:35
25

As other have answered, the result is exactly the same, None is returned in all cases.

The difference is stylistic, but please note that PEP8 requires the use to be consistent:

Be consistent in return statements. Either all return statements in a function should return an expression, or none of them should. If any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable).

Yes:

def foo(x):
    if x >= 0:
        return math.sqrt(x)
    else:
        return None

def bar(x):
    if x < 0:
        return None
    return math.sqrt(x)

No:

def foo(x):
    if x >= 0:
        return math.sqrt(x)

def bar(x):
    if x < 0:
        return
    return math.sqrt(x)

https://www.python.org/dev/peps/pep-0008/#programming-recommendations


Basically, if you ever return non-None value in a function, it means the return value has meaning and is meant to be caught by callers. So when you return None, it must also be explicit, to convey None in this case has meaning, it is one of the possible return values.

If you don't need return at all, you function basically works as a procedure instead of a function, so just don't include the return statement.

If you are writing a procedure-like function and there is an opportunity to return earlier (i.e. you are already done at that point and don't need to execute the remaining of the function) you may use empty an returns to signal for the reader it is just an early finish of execution and the None value returned implicitly doesn't have any meaning and is not meant to be caught (the procedure-like function always returns None anyway).

Fabiano
  • 612
  • 8
  • 13
5

In terms of functionality these are all the same, the difference between them is in code readability and style (which is also important to consider)

Yehuda Schwartz
  • 3,378
  • 3
  • 29
  • 38