Python handles globals badly.

Chris Angelico rosuav at gmail.com
Thu Sep 10 20:33:42 CEST 2015


On Fri, Sep 11, 2015 at 4:13 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> Sometimes they might be. But in general, I think it is meaningless to expect
> a imperative command to have a return result. The whole point of an
> imperative command is that it operates by side-effect.
>
> For example, what would `del x` return if it were an expression instead of a
> statement? I can think of two reasonable alternatives, but both feel a bit
> wrong to me.
>
> (1) Return True if x was successfully unbound, False if it wasn't. Except
> that raising an exception seems more Pythonic, in which case returning True
> seems redundant. It will *always* return True, unless there's an exception.
> So why bother? We only bother because there's no way to *not* return a
> result if "everything is an expression".
>
> (2) Return None, like functions do by default. But again, it only returns
> None, not because None is a meaningful thing to return, but because we
> don't actually have a way to say "it doesn't return anything".

Yes, or: (3) Return the old value that x contained, the way dict.pop()
does. That makes it a "destructive retrieval" rather than simply a
destruction operation.

> Or os.abort. The docs for that say:
>
> Help on built-in function abort in module posix:
>
> abort(...)
>     abort() -> does not return!
>
>     Abort the interpreter immediately.  This 'dumps core' or otherwise fails
>     in the hardest way possible on the hosting operating system.
>
>
> So, what would os.abort() return, if everything is an expression?

Since this is in the os module, and is thus a thin wrapper around
lower-level operations, I could imagine it returning an error code
(the way the C-level exec functions do - if they succeed, they don't
return, but if they fail, they return an error number); in Python,
it'd be best to have it either abort the process (and thus not
return), or raise an exception (and thus not return).

But abort functions are a rarity. It's not a problem to have a rule
"all functions must return something" (as Python does), and then have
functions that never actually use the normal return path:

def raise_(exc): raise exc
raise_stopiteration = iter([]).__next__
raise_typeerror = lambda: ""()

Calling one of these functions is *syntactically* an expression, but
at run time, it'll never actually get as far as producing a value. If
it's at all possible for the operation to, based on run-time
information, NOT abort, then it absolutely has to be able to return.

> Because that's the definition of an expression in this context. An
> expression is evaluated to either return a result, or raise an exception.

I'd define it more simply: An expression always produces a result.
It's possible that, during the evaluation of an expression, an
exception will be raised; if that happens, evaluation stops. Doesn't
matter whether the expression itself caused that, or if an OS-level
signal did (eg triggering KeyboardInterrupt), or if the expression was
"yield 1" and an exception got thrown in. But yes, an expression is
something that generates a result; a statement isn't.

ChrisA


More information about the Python-list mailing list