Both expressions and statements are syntactic constructs. As you observed, expressions have values. Evaluation is the process of determining the "canonical" value of the expression, the value whose canonical value is itself.
For example, the canonical value of the three expressions 3 + 5
, 2 * 4
, and 8
is 8
. The canonical value of print("hello world")
is None
. The canonical value of ''.join(["foo", "bar"])
is "foobar"
.
The eval
function can be used to find the canonical value of an expression.
>>> eval('8') == eval('3 + 5') == eval('2 * 4')
True
(The canonical value of the chained comparison is True
, indicating that 8
is indeed the canonical value of 8
, 3 + 5
, and 2 * 4
. Part of the job of the interactive interpreter is to print the canonical value of an expression if that value is not None
.)
Statements don't have values. That doesn't mean they can't produce a value; it just means you can't access the value. Most statements really don't have a value. The exception is the expression statement, which is, as the name implies, a statement that consists of a single expression. Expression statements are what allow you to have a function call act as a statement by itself without needing to embed it in a meaningless assignment statement to capture its return value. That is, we can write
print("Hello, world!")
instead of
whocares = print("Hello, world!") # assert whocares is None
Any expression can be used as an expression statement, but only expressions that include at least one side effect (mutating an object, writes to a file, etc) are useful as expression statements.