Here are additional resources about Python grammar:
In the previous lesson, I gave you a quick overview of the course. In this lesson, I’m going to talk about the basic usage of
The built-in function
eval() can take a subset of the Python language known as an expression. Common expressions are things like doing math.
Here, I’m passing a string to
eval() that is a Python multiplication.
eval() takes the contents of it, parses it, compiles it, runs it as Python, and then returns the result.
Here’s another one using exponential. Same concept. You can also use functions. Because
sum() returns a value, the result of
eval() is the evaluation of that sum of the list of numbers.
eval() also has access to the global namespace. I can create a variable here and then evaluate using that variable. There are ways of further restricting this, but I’ll show you those later.
Here’s the signature for
eval(). It takes an expression and optionally two dictionaries—one for globals, one for locals.
01:10 An expression is a subset of the Python language that includes literals, names, attributes, operations, or functions that return a value.
Let’s go over those one by one. A literal is data—things like an integer, a string, a float, a Boolean value, or even a list mixing these things. Names are variables, something that can be assigned. So in the statement
x = 3,
x is the name.
x = 3 is a statement and not an expression. The assignment itself can’t be used in
eval() but the
x can be. Attributes are similar to names but instead of being global, they’re part of a named object.
If you had an object named
part with an attribute
.serial_no, you could access that inside of
eval(). Operations are expressions that combine literals with an operator. Common ones are things like math.
2 + 3 is a literal, operator, and a literal. This is together an expression. Similar with multiplication, subtraction, and even Boolean evaluation.
value == result is an expression. Finally, you can also use any function that returns a value. You can write one for Fibonacci, you can use functions from the
math library, or methods from your objects as long as they return something. Those were expressions.
What’s not an expression? Well, for starters, assignment.
eval() won’t take
"x = 100". That’s a statement. Statements aren’t allowed.
It raises a
SyntaxError and indicates what the problem is—in this case, the operation of assignment, the equals (
If I want to use
x, I have to do it outside of
eval(). Conditionals that are usually multiline—those with colons (
:) in them—are also statements.
This is also considered a
SyntaxError. Invalid expressions also cause problems. Technically this isn’t a statement but if I haven’t finished the expression, it will also cause a
So, here are things that aren’t expressions. Like I showed you in the example, assignments are statements. Conditionals and
import also is considered a statement.
This means if you want to use something like the
math library inside of
eval(), you’ll have to do the import outside of the
Any looping structures like
while are also considered statements. And finally, any sort of exceptions—
raise, et cetera.
eval() method has a cousin called
exec(). The signature is very similar to the
exec() will run any kind of code—statements and expressions included, so it’s the superset. Unlike
exec() has no return result.
Even if the contents of the
exec() are a function call that returns something,
exec() itself will not return a result. These two built-in functions have similar purposes—running code—but slightly subtle different calling structures, so you can do different kinds of things with them.
This course concentrates on
eval(). I just thought I’d point out
exec() so that you were aware it was there if you want to go and play with it.
I’m going to spend a little time going off on a tangent here. I want to talk a little more about expressions and statements inside of Python. What I’ve covered so far is good enough for your understanding moving forward with
04:39 If you’re bored by the details of the compiler and how parsers work, feel free to skip on to the next lesson. Otherwise, hang on and I’ll show you some deep-dive stuff in the language of Python.
04:50 The syntax of a programming language is specified by something called its grammar. In Python 3.9, a new kind of parser was introduced in order to take advantage of a more flexible grammar.
05:01 This parser is called a PEG parser, for Parsing Expression Grammar. So far, nothing new has been introduced to the language that couldn’t be done using the old-style grammar.
05:11 3.9 is a transition. And the concepts that I’m going to show you also exist inside of earlier versions, they’re just notated differently. A grammar specification indicates to a language how to parse the code file.
05:26 You can find the full specification for Python’s grammar at this URL. In the following few slides, I’m going to highlight a few key parts of the PEG and show you the differences between expressions and statements inside of the grammar specification.
05:44 Grammars aren’t specified themselves in Python. The language here that specifies the grammar is specific to the PEG. A common language for specifying coding grammars is something called BNF, Backus–Naur form. Prior to Python 3.9, Python used something called the EBNF, the extended Backus–Naur form.
06:05 A PEG grammar introduces a couple of new pieces, and so what’s being presented here is a hybrid of EBNF and PEG. The key thing to understand here is that it’s a recursive definition.
Everything shown in light blue is like the concept of a variable or a declaration. The third line down here defines something specific for
eval() in the grammar, saying that it will take expressions as well as newlines and endmarkers.
Compare that to the line above it, which is interactive, like the REPL, which takes a statement. So already here at the beginning of the PEG, you can see that the language breaks down into this concept of expressions and statements. Further down in the grammar, you’ll find the definition of
It’s a compound one based on the definition of
expression, singular, and
expression can be combined with other
expression declarations to create the plural. Below that is the definition of the singular
It can be comprised of a lambda, a disjunction, or a conditional disjunction. The conditional disjunction is one where
else is happening inside of the same line without a colon. These kinds of single-line conditionals aren’t that common in Python, so you may not have run into this before, but this would be something like
x if y > 3 else y.
That would return the value of
y is greater than
3, otherwise it would return the value of
y—all in a single line.
Continuing further into the grammar, you can see definitions for a
disjunction is comprised of conjunctions. Conjunctions are comprised of inversions, inversions are comprised of inversions or comparisons, and this definition just keeps drilling down. Further down, you get into the concept of terms. Moving on, you’ll see that a
term consists of a
term and certain kinds of operators.
This is where you can start seeing things like multiplication and division. At the base of all this is the concept of an
atom. The atoms are the things that are actually parsed out.
These are things like text inside of your file that are keywords. Booleans—
None placeholder, literals like numbers, lists, tuples, dictionaries—all those things that I described earlier that can be used inside of an expression inside of
08:37 So think back to a couple of slides ago where the definition of an expression consisted of disjunctions, disjunctions of conjunctions, and all this moves down.
08:46 Because this is recursive, once you combine all those concepts, you’ll have some mix of atoms and operators, which result in the expressions that I’ve shown you so far.
By contrast to expressions, let’s look at the definition of an
assignment. There’s a lot going on here. I don’t want to go into every last little piece, but you can see that the
assignment is comprised of names, expressions, and then other kinds of sub-components like
There’s also a definition for augmented assignments, which are just assignments which also use things like the plus equals (
Moving further into the grammar, you can find the definition of
statements. More recursion here.
statements plural consists of multiple
statement declaration consists of
compound_stmt (compound statements) or
simple_stmt (simple statements).
simple_stmt consists of
small_stmt (small statements) and some punctuation to go off with that. Digging into
small_stmt, and you’re starting to see things here that actually feel familiar to a Python programmer. A
small_stmt can be an
return_stmt (return statement), an
import_stmt (import statement),
nonlocal. Grammar further defines all of these concepts, but you get a sense here that the
small_stmt is kind of like the
atom inside of the
Just like the
atom where you start to see components like literals and
False that seem familiar from the programming language, the
small_stmt consists of declarations that also feel like things that you’re probably used to—returning and importing, et cetera.
10:29 If you’re interested in the PEG grammar or more details about how all of this stuff works, there are some further reading links inside of the description. For now, I just wanted to give you a rough taste as to how all these pieces fit together and a better feeling as to the difference between an expression and a statement.
Next up, I’ll show you more of the parameters for
eval() and how to take advantage of them.
Become a Member to join the conversation.