Reputation: 68260
If you look at the Python bytecode compiled from modules, you'll see at the end:
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
I.e. a return
is perfectly valid at the root level of a module. However, if you try to use it in the source code, you get:
SyntaxError: 'return' outside function
Why?
This is of course a language design decision. But why was it taken? A return
is often quite useful in a module. E.g. I sometimes want to write this code at the beginning of a module:
import sys
if sys.platform != "linux2":
print "your platform is not yet supported"
# define some stubs
def foo(): pass
def bar(): pass
return
And I don't want to raise an exception there (because that would result in the module not loading which I don't want).
Actually, I hacked some code together which can manipulate the Python bytecode on the fly and just do the return (or in my case jump to the end where the return is done). This works. The only reason it is CPython only is because there is no standard way to manipulate a code object.
Here is the code.
For possible answers: I would prefer real evidence, some past statements from Guido van Rossum or so about this, not so much just any random discussion. I of course can this of both advantages (as presented already) and disadvantages myself but I don't really see the big reason against it.
Upvotes: 28
Views: 6096
Reputation: 18635
This isn't a "why" (I suspect the answer to that is just "return
belongs in a function and there's no compelling reason to put it in top-level module code"). But it's a tidy workaround that you may not know about. Your code can be refactored as follows without adding much complexity:
import sys
def main():
global foo, bar
if sys.platform != "linux2":
print "your platform is not yet supported"
# define some stubs
def foo(): pass
def bar(): pass
return
main()
Upvotes: 0
Reputation: 310097
I would guess that this is a decision on the part of the python devs because it forces the user of the module to deal with the fact that their system isn't supported (rather than getting the developers of the module to guess what should happen). Imagine their surprise when they run the code on a windows machine and all of a sudden module.foo()
doesn't work as they expected. (Your warning print
statement could be completely buried in all sorts of other garbage that might get dumped to stdout).
I think that the most idomatic way to handle this is to raise an ImportError
or NotImplementedError
. Then the user can decide if they can live without this module and proceed, (by catching the exceptions), or if their program should crash and burn right there.
Upvotes: 7