Rules of Python

To help you understand how Python works, this document explains the rules that Python follows when running your code. Note that as we cover more advanced topics, we will teach you about new rules, but the basic rules are quite simple.

Core rules

When you press the "run" button in Thonny to run a file, or the "run" button in a Jupyter notebook to run a cell, here are the rules that Python follows:

  1. Start at the very first line of code.
  2. When running a line of code, first simplify any expressions on that line. To simplify an expression, Python simplifies things one step at a time, and the possible simplification steps are as follows:
    • Replace a variable name with the current value of that variable.
    • Combine two values using an operator. The two values to be combined must already be fully simplified.
    • Replace a function call whose argument(s) have been completely simplified with the result of that function call. Note that during this step, the function being called may produce side effects. Note that each built-in function has its own rules for what the result will be (and for what side effect(s) will occur) based on the argument(s) you give it.
  3. Once all expressions have been fully simplified down to individual values, if the line of code is an assignment statement, the value of the variable named in the assignment statement will be updated. If that variable already existed, its old value will be forgotten, or if not, that variable will be created. Either way, the simplified value of the expression on the right-hand side of the equals sign becomes the new value of the variable named on the left-hand side of the equals sign.
  4. After all expressions have been simplified into values, and an assignment has been made (if there was one) Python moves on to the next line of code in the file or notebook cell and repeats this process. When the last line of code has finished executing, the program stops.

Additional notes:

Tips for programming

Based on these rules, here are some important ideas to keep in mind:

Rules for functions

The def statement adds to the core rules above in the following ways:

  1. In rule #2, for running a line of code, if that line of code is a function definition (i.e., if it starts with the keyword def), instead of applying the normal simplification/assignment process, Python does the following:

    1. It gathers all of the lines of code which are indented at the same level as the first line of code following the def line (including that first line of code).
    2. Without simplifying anything or running any of that code, Python stores that code into a box (just like variable assignment) and names that box according to the function name which appears after the def keyword. Python also remembers the parameter names and the order of parameters which are specified on the definition line.
    3. Python then proceeds to execute the next line of code that comes after all of the indented code that it collected; that line of code must match the indentation level of the def statement, or an IndentationError will occur.
  2. In addition to the above process for gathering and storing code, rule #2 part 3 now includes the idea of simplifying a function call to a custom function that's been defined using def. When simplifying a custom function call, we follow the following rules to figure out the result value which will replace the function call in the expression we're simplifying:
    1. First, Python creates a new function call frame for processing the custom function, which is a special zone that can store temporary variables which will only be available during the processing of that function.
    2. Second, Python takes each argument value from the function call that we want to simplify, and based on its order among the arguments, it figures out which parameter of the function it is calling that argument corresponds to. For each of these parameters, an assignment is made within the new function call frame that assigns that parameter to hold the associated argument value.
    3. Next, Python executes each line of code that was stored when the function was defined, according to all of the normal rules for running code. During this process, any assignments that are made create or modify variables that are in the current function call frame, although variables from the whole program context can still be used as part of an expression (they just can't be modified).
    4. If Python encounters a return statement (a line of code that starts with the keyword return) it first fully simplifies the expression that follows the return keyword (if there is one), and then the simplified value of that expression becomes the result of the function call (no further lines of code will be executed). If there is no expression after the return keyword, then the result value will be the special value None.
    5. If there is no return statement, when the last line of code in the stored function is completed, the special value None becomes the result value.

Notes:

Rule for conditionals

The if statement adds to the core rules above in the following ways:

  1. In rule #2, for running a line of code, if that line of code is a conditional (i.e., if it starts with the keyword if), instead of applying the normal simplification/assignment process, Python does the following:
    1. It gathers all of the lines of code which are indented at the same level as the first line of code following the if line (including that first line of code).
    2. If simplifies the condition part of the conditional (the expression between the if and the colon at the end of the line) and determines whether that simplified value is "truthy" or "falsey" (see below).
    3. If the condition's simplified value is truthy, the lines of code that were collected in step 1 are executed per all of the usual rules of Python (including these rules). However, if the simplified condition value is falsey, those lines of code are skipped.
    4. If the line of code following the indented block is just else:, then the indented block of code following that else will be skipped if the first block of code was executed, or executed if the first block of code was skipped (the two blocks are mutually exclusive). If there are multiple elif blocks above an else, the else is only executed if all of them are skipped.
    5. If the line of code following an if (or elif) block starts with elif, the condition on that line will be simplified only if all connected if and elif blocks above it were skipped, and that condition's truthy/falsey status will determine whether we execute or skip the block underneath it.

For the purposes of conditional choices, "truthy" and "falsey" values are defined as follows:

Rules for loops

The while and for statements add to the core rules above in the following ways:

  1. In rule #2, for running a line of code, if that line of code is a while loop (i.e., if it starts with the keyword while), instead of applying the normal simplification/assignment process, Python does the following:

    1. It gathers all of the lines of code which are indented at the same level as the first line of code following the while line (including that first line of code). This is the loop body.
    2. It simplifies the condition expression which follows the keyword while (this is the loop condition). If the simplified value of that expression is truthy, the loop body is executed using all of the normal rules for executing code, including these rules about loops. Otherwise, the loop body is skipped and execution continues after it.
    3. If the loop body was not skipped, when it is finished (assuming it was not interrupted by something like a return) the loop condition is simplified again, and if it still simplifies to a truthy value, the loop body is run again. This process continues until the loop condition simplifies to a falsey value, at which point the loop body is skipped and the loop ends. If the loop condition never becomes falsey, the loop will continue indefinitely.
  2. In rule #2, for running a line of code, if that line of code is a for loop (i.e., if it starts with the keyword for), instead of applying the normal simplification/assignment process, Python does the following:
    1. It gathers all of the lines of code which are indented at the same level as the first line of code following the for line (including that first line of code). This is the loop body.
    2. The for line must name a loop variable, followed by the in keyword, and then the loop expression. Python simplifies the loop expression once, and the result must be a sequence (which we call the loop sequence). Note that the loop expression is simplified only once, unlike the loop condition in a while loop.
    3. Once the loop sequence has been determined, Python assigns the first item in the loop sequence as the value of the loop variable and then executes the entire loop body following all of the normal rules of Python, including these ones. When the loop body is finished (as long as it was not interrupted, e.g. via return), Python will assign the second item from the loop sequence into the loop variable and execute the loop body again, repeating the entire process for each of the items in the loop sequence. (If the loop sequence is an empty sequence, then the loop body is never executed). Each execution of the loop body is called an iteration.
    4. Once all iterations of the loop have finished, execution continues with the code that comes after the indented loop body.