In Python it's possible to create a procedure that has no explicit return. i.e.:
def test(val):
if 0 == val:
return 8
Further, it's possible to assign the results of that function to a variable:
>>> a = test(7)
>>> print `a`
'None'
Why the heck is that? What language logic is behind that baffling design decision? Why doesn't that simply raise a compiler error?
EDIT: Yes, I realise that it works that way. Thanks. My question is WHY? It seems like such a sure fire way to introduce subtle bugs into your code. And it seems, as was mentioned below by e-satis, to go against the very wise pythonic adage that "explicit is better then implicit".
So, what's up with this? Is it just a design oversight or a simplifying assumption or a deliberate, considered decision?
EDIT: Would everyone agree that expressing the intent this way is much better:
def test(val):
if 0 == val:
return 8
else:
return None
If so, why would Python prefer the former style to raising a compile time exception?
EDIT: S.Lott brings up the point explicitly (and others do too, his just seems most clear to me) that this behaviour is a result of the fact that Python is a dynamic language and therefor can't check at compile time, the run time behaviour of the system.
Since there is no distinction between procedures (those functions that return no values) and functions (those that do), that there is nothing to enforce at compile time. Which means that when we come to run-time behaviour, we either have a catastrophic failure in some cases (we throw an exception) or we silently fail assuming that the programmer knew what they were doing and understood the default behaviour.
The pythonic way is to do the latter, the C-style way is to do the former.
That seems to make sense as a good reason to do it that way.S.Lott's clear justification is buried in the comments to the accepted answer so I thought it best to summarise here.
I'll hold off on accepting the answer for a bit to see if S.Lott makes an official answer. Otherwise, I'll give the points to开发者_Python百科 SilentGhost.
While every function might not have an explicit return it will have an implicit one, that is None
, which incidentally is a normal Python object. Further, functions often return None
explicitly.
I suppose returning None implicitly is just an ease-of-use optimisation.
P.S. I wonder what you propose compile would do in the following case:
def t():
if True:
return 'ham'
P.P.S. return
statement indicates that something needs to be returned, be it None
, 42
or 'spam'
. Some functions, however, don't really return anything, like list.sort
or __init__
, therefore it would be an overhead to require a return None
statement at the end of each __init__
.
Python never checks for human misbehavior. The language philosophy is to assume that programmers are grown up adults and know what they are doing.
Since :
- Python is an autodocumented language, so you'll know in a blink what returns a function;
- Python uses duck typing, so getting None by default can ease dynamic function call a lot.
Returning None make more senss than raising an error.
E.G :
function_stack = [func1, func2, func3]
for f in function_stack :
a = f()
if a is not None :
# do something
No matter if f is f() is a function or a procedure. There is no such thing in Python. You can apply all the function, and process output if there is any.
Heh. Coming at it from a Java perspective, your question is obvious. It should throw an error.
But if you came at it from a Perl perspective, it's not obvious at all. You're setting a variable to no value, big deal.
It's all about the typing. Like Java, Python is strongly typed, but unlike Java, it is also dynamically typed. Most dynamically typed languages allow shenanigans like this.
It's beautiful ...
It returns None
in the case where val != 0
which to me make sense.
Python 2.6.1 (r261:67515, Jun 18 2009, 17:24:16)
[GCC 3.3.3 (SuSE Linux)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def test(val):
... if 0 == val:
... return 8
...
>>> a = test(8)
>>> print a
None
>>> print test(0)
8
>>>
Do you have any arguments why you think the behavior is wrong?
You can use c++ if you need strong compile time type checking but for python it seems extremely flexible and I assume that's what you want when you selected python for your task.
What compiler? The bytecode compiler checks your code for syntax on import, but syntax doesn't include "check all paths for a return". So when test() gets called at runtime, and the value of x isn't 0 and we just fall out of the function, what should we do? return 0? Why not -1, or "", or -infinity? So a nice neutral value should always be returned in the absence of an explicit return statement - and that value is None. This is a standard feature of the language - welcome to Python!
It's because of the dynamic typing.
You don't have to make the distinction between, say, turbo pascal's procedure and function. They are all function, they return None
by default, which is logically correct. If you don't say anything it returns nothing, None
.
I hope it make more sense now-
精彩评论