Does it return by reference[?]
Effectively yes. When you return an object, the id (i.e. memory address) of the object inside the function is the same as the id of the object outside the function. It doesn't make a copy or anything.
[...] or does it return the value directly?
If you're saying "is it like the 'pass-by-value' argument passing system of many programming languages, where a copy is made and changes to the new value don't affect the original one? Except for returning values instead of passing them?", then no, it's not like that. Python does not make a copy of anything unless you explicitly tell it to.
Does it resolve the expression and returns that?
Yes. Expressions are almost always resolved immediately. Times when they aren't include
- when you have defined a function (but haven't executed it), the expressions in that function will not have been resolved, even though Python had to "pass over" those lines to create the function object
- when you create a lambda object, (but haven't executed it), ... etc etc.
In summary, is it better to store an expression's value into a variable and return the variable, or is it also perfectly fine (efficiency, and PEP-wise) to return the expression as a whole?
From the perspective of any code outside of your functions, both of the approaches are completely identical. You can't distinguish between "a returned expression" and "a returned variable", because they have the same outcome.
Your second function is slightly slower than the first because it needs to allocate space for the variable name and deallocate it when the function ends. So you may as well use the first approach and save yourself a line of code and a millionth of a second of run-time.
Here's an example breakdown of the byte code for two functions that use these different approaches:
def f():
return 2 + 2
def g():
x = 2 + 2
return x
import dis
print("Byte code for f:")
dis.dis(f)
print("Byte code for g:")
dis.dis(g)
Result:
Byte code for f:
2 0 LOAD_CONST 2 (4)
2 RETURN_VALUE
Byte code for g:
5 0 LOAD_CONST 2 (4)
2 STORE_FAST 0 (x)
6 4 LOAD_FAST 0 (x)
6 RETURN_VALUE
Notice that they both end with RETURN_VALUE
. There's no individual RETURN_EXPRESSION
and RETURN_VARIABLE
codes.