1
$\begingroup$

In Python, this is a valid program

def PrintWorld():
    print('World')

print('Hello')
0
'beautiful'
True
None
0 < 0
3, 3
lambda c:3
PrintWorld()

All it does is print 'Hello World' on two lines. The expressions are 0, 'beautiful', True, None, 0 < 0, 3, 3, and lambda c:3 are ignored and I'm wondering why.

I realize that this behavior allows Python to treat the function call PrintWorld() like any expression: It is an expression with value None in the course of whose evaluation the function is called. In a sense, this means that both 'beautiful', PrintWorld(), and a hypothetical expression with side effects like PrintWorld() is None could be treated the same on some level.

I also realize that this is related to interactive mode: When you run the Python interactively, giving only a stand-alone expression will result in its value being printed.

Still, why should non-interactive mode accept these expressions (except function calls)? In my eyes they open up the possibility for pointless code without offering anything in return.

And, as a follow-up: If you do allow these stand-alone expressions, why have comments or a pass statement in the language when you could just use a stand-alone expression instead? Sure, "explicit is better than implicit", but it's also valuable to keep the language small.

As research I googled and searched stack overflow and CS stack exchange. I also looked into the Python language definition.

$\endgroup$
4
  • $\begingroup$ I think python just evaluates them. To use their values is up to you. It just makes "compiling" (its not a compiled language) python easier I guess, but honestly, Im not an expert in this area so I don't know. $\endgroup$
    – nir shahar
    May 11 at 9:58
  • 1
    $\begingroup$ Expressions and simple statements $\endgroup$
    – Pål GD
    May 11 at 10:03
  • 1
    $\begingroup$ It is possible to define side effects for pretty much all of those expressions. You could hypothetically want to evaluate an expression for the side effects $\endgroup$
    – mousetail
    May 11 at 11:54
  • $\begingroup$ @mousetail How would you do that for the examples I gave? $\endgroup$ May 11 at 12:01
4
$\begingroup$

The python creators decided that any expression is valid as a statement. While not all expressions are useful as statements, it would make the language more complex to have to remember which expressions may be statements and which can not.

A second reason is that many expressions that may seem "safe" can still have side effects, making it useful to evaluate them without using the return value.

Operators

Operators are the most obvious examples of expressions that you can easily add side-effects to. In your example 0 < 0 is equivalent to 0.__le__(0). You can overwrite the __le__ method or any operator special method to do whatever you want, including writing to a file or incrementing a counter.

You can also evaluate operator expressions just to make sure the types are compatible. For example, if you are going to do a very long computation on variables a and b that ends by dividing some value based on a by b you might evaluate a/b at the start of your function as a quick and dirty way to make sure the types can be divided and that b is not zero before spending a lot of time calculating.

Strings

Strings don't typically have any side effects, but string expressions are frequently used in python code as a type of comment. Specifically, docstrings are triple-quoted strings right after the heading of a class or function, and will be assigned to __doc__.

Variables

Evaluating variables has one important function: It will crash if the variable doesn't exit. For example, suppose I have a module server.py that must be configured server.host = 'localhost' before starting. I could write this:

try:
    host
except NameError:
    raise ConfigurationException("must set host")

Tuples

The tuple expression a, b where a and b are expressions will evaluate any side effects from a b.

Others

Ok, there is little use for a loose None. However, only disallowing None, True, False, Ellipsis, NotImplemented, and ... would be a unnecessary special case that would make the language harder to learn for little benefit.

$\endgroup$
1
$\begingroup$

Python can be used interactively, in which case the bare expression's value (if any, it might be None) is printed out. If running a script or as part of a function, the value is just discarded.

If you look closely, Python only has functions (no procedures in e.g. Pascal sense or SUBROUTINE for Fortran that specifically don't return a value at all). Like in C, procedures are fake, functions that return None either explicitly, doing a bare return, or by not executing return at all.

Why Python is architected this way is anybody's guess. You'd have to ask the people in charge. It does simplify the grammar somewhat and presumably also makes the parsing/processing simpler/faster, besides making interactive use cleaner.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.