return, return None, and no return at all?
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.
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
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
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.
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
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.
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 disdef f1(): print "Hello World" return Nonedef f2(): print "Hello World" returndef 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_VALUEdis.dis(f2) 9 0 LOAD_CONST 1 ('Hello World') 3 PRINT_ITEM 4 PRINT_NEWLINE 10 5 LOAD_CONST 0 (None) 8 RETURN_VALUEdis.dis(f3) 14 0 LOAD_CONST 1 ('Hello World') 3 PRINT_ITEM 4 PRINT_NEWLINE 5 LOAD_CONST 0 (None) 8 RETURN_VALUE
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
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...