Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Python essentials for this course

This appendix is a small bridge into the Python used in Practical Numerical Methods. It concentrates on the language patterns, NumPy operations, and Matplotlib calls that appear in the phugoid lesson. It is not a complete introduction to programming.

If Python is new to you, work through the sections in order in a practice notebook. Type the examples rather than copy-pasting (or only reading them), predict what each cell will do, and change one value at a time. If you have used Python before, scan the headings and use the final checklist to find any rusty areas to come back to.

You do not need to memorize syntax. By the end, you should be able to read a short numerical program, make small changes, and explain what its main pieces do. Keep this appendix open as a reference when you begin Phugoid Motion.

A notebook is a conversation with Python

A notebook contains two main kinds of cells:

  • A Markdown cell contains explanations, equations, headings, and links. This text is in a Markdown cell.

  • A code cell contains Python instructions. Run a selected cell with Shift–Enter. Python evaluates the code and may display a result below it.

If your previous experience is HTML and CSS, this is the important shift: HTML describes structure and CSS describes appearance, while Python statements perform operations and create or change values. Their order matters. Python also uses indentation as part of its syntax, not only for visual alignment.

Run the next cell. Python evaluates the arithmetic expression and displays its value.

A notebook runs on a background process called the kernel, which maintains the state of your session. The state is the condition of your notebook at any given moment. When a cell assigns a value to a name, later cells can use that name. This is convenient, but it also means that running cells out of order can leave stale or missing values. When something surprising happens, restart the kernel and run the cells from the beginning. See Recover a linear account for the course workflow.

Names, values, and expressions

The = symbol is assignment: it binds a value to a name. Read distance = 120.0 as “assign the value 120.0 to the name distance” (or "distance is 120.0). You should choose names that describe the quantity they represent, and including units in a name can prevent mistakes when the units are not otherwise obvious.

Python’s common arithmetic operators are +, -, *, /, and ** for powers. The expression speed**2 means speed2speed^2; ^ does not mean exponentiation in Python. Parentheses control the order of operations, just as they do in algebra. A # begins a comment that Python does not execute.

The value 120.0 is a floating-point number, or float; the value 120 is an integer, or int. Numerical code often uses floats because measured quantities and computed results are not usually whole numbers. You rarely need to manage these types explicitly at first, but error messages may mention them.

Use == to ask whether two values are equal. It is different from assignment with =. Comparisons such as <, <=, >, >=, ==, and != produce either True or False.

print(...) is a function call: the parentheses tell Python to run the function with the value inside them. Text in quotation marks is a string. An f-string begins with f and inserts values at locations marked by braces. In {speed_m_per_s:.1f}, .1f requests one digit after the decimal point.

Imports give us scientific tools

Python itself provides the language, while packages provide additional tools. This course uses NumPy for numerical functions and arrays and Matplotlib for plotting.

An import statement makes package code available. The names np and plt are conventional aliases: they reduce typing and show where calls such as np.sin(...) and plt.subplots(...) come from. The dot means “look up this name inside that package or object.”

NumPy’s trigonometric functions use radians. Convert an angle supplied in degrees at the boundary between user input and the calculation. Floating-point computations may differ by tiny round-off amounts, so np.isclose(...) is usually a better numerical check than exact equality.

An assert records an expectation. If the expression after assert is True, execution continues silently. If it is False, Python raises an AssertionError. Assertions are useful quick checks while exploring; later in the course, important reusable code will receive more systematic tests.

Functions name a reusable calculation

A function groups a calculation behind a name. The def line gives the function its name and its input parameters. The indented lines below it form the function body, and return sends a result back to the caller. Python requires the indentation; four spaces is the standard.

The triple-quoted first line is a docstring, a short explanation of what the function does. It is optional, but you should always add it when you define a function, to keep the code documented.

Defining a function does not run its body. Call it with parentheses when you need the calculation, and the function code will run then. If it has an error, you will see it the first time you call it. Arguments may be supplied by position, as in the first call below, or by parameter name, as in the second. Named arguments make the meaning clear when several inputs have similar-looking values.

A parameter with a value in the def line has a default. The caller may omit that argument or override it. In the next function, dt is optional and has the default value 0.1. Names created inside a function, such as new_position, are local to that call and not available outside the function.

Conditions choose what happens

An if statement runs an indented block only when its condition is true. elif checks another condition, and else handles what remains. The words and, or, and not combine or reverse conditions.

A function should sometimes reject an input rather than calculate a meaningless value. raise ValueError(...) stops the function and reports a useful message.

The last line uses a chained comparison: 0.0 < time < 20.0 asks whether time lies between the two limits.

Try travel_time(120.0, 0.0) in your practice notebook. The red traceback (error message) is information, not a catastrophe. Read its final line first: it names the error type and gives the message. Then work upward to find the line in your code that triggered it. Restore a positive speed before continuing.

Lists store a growing sequence

Square brackets create a list. Python counts positions from zero, so values[0] is the first item. The index -1 means the last item. The method .append(...) adds one item to the end, and len(...) reports how many items the list contains. A method is a function attached to a particular object; the dot in values.append(...) means “use this list’s append operation.”

Tuples package a fixed group of values

A comma-separated group such as (2.0, 4.0) is a tuple. Tuples are useful for a point’s coordinates, or for several values returned together. Unpacking assigns the items to the same number of names.

NumPy arrays hold numerical data

Lists are convenient while values are being collected. A NumPy array is more convenient after the data are complete because arithmetic acts element by element. np.asarray(...) converts an existing sequence to an array, while np.array(...) constructs one directly.

In the next cell, the unary minus in height_values = -depth_array changes the sign of every element. The same operation on a Python list would fail.

NumPy also represents special floating-point values. np.inf means infinity, and np.isinf(...) tests for it. You will see this in the phugoid model when a straight path has an infinite radius of curvature.

Loops repeat an update

A for loop repeats its indented body of code. range(4) supplies the integers 0, 1, 2, and 3, so this loop performs four updates. The current value of step can help us inspect the process.

Sometimes the counter is not used. The name _ conventionally means “this value is intentionally ignored.” The break statement stops a loop early. Here we stop before saving a non-positive depth because the model is defined only for positive depth.

Matplotlib turns arrays into a plot

plt.subplots() returns two objects: a Figure and an Axes. We unpack them into fig and ax. The Axes object has methods for plotting the data, labeling the axes, and controlling the grid. Keyword arguments such as marker="o" name optional settings.

The r before a label string makes it a raw string, which is convenient for mathematical notation containing backslashes. You may copy and paste this mechanical plotting syntax while you are learning what each call controls.

Put the pieces together

The following small program uses the same Python patterns as the phugoid tracer without its changing curvature. It traces a straight flight path from an initial positive depth z0z_0. The flight-path angle is supplied in degrees and is positive above the horizontal. Each loop iteration advances a distance dsds and stops before the path reaches z≤0z\leq0.

Before running the function, predict the first new point for z0=2z_0=2, θ0=30∘\theta_0=30^\circ, and ds=1ds=1. You should be able to calculate it with cos⁡30∘\cos 30^\circ and sin⁡30∘\sin 30^\circ.

Read the function from top to bottom and identify the validation, conversion, initial state, repeated update, stopping condition, and returned data. Then call it and unpack the two returned arrays.

A few focused checks compare the calculation with our prediction and the model’s domain. np.all(...) asks whether every element of a Boolean array is true.

Keep computation and plotting separate when practical. The function above returns data without deciding how they must be displayed; the next cell plots those data. Because zz is depth measured positive downward, we plot −z-z to display upward displacement in the familiar direction.

Practice before the phugoid lesson

Do these in your practice notebook. Predict first, change one thing, run the relevant cells, and explain the result in a Markdown cell.

  1. Call trace_straight_path() with θ0=0\theta_0=0. What should happen to z? Check your claim with np.isclose(z[-1], z[0]).

  2. Omit n_steps and ds from a call. Which values does the function use? Override only ds with a named argument.

  3. Supply a negative z_0. Read the final line of the traceback and explain why the function rejects that input.

  4. Change the angle to −30∘-30^\circ. Predict the signs of the changes in xx and zz before plotting.

  5. Temporarily change the minus sign in the update for z_new to a plus sign. Which check or visual feature reveals the defect? Restore the correct sign afterward.

If an edit leads to confusing state, restart the kernel and run all cells from the beginning. That is normal notebook practice, not a failure.

Syntax map

PatternRead it as
name = valueAssign a value to a name
left == rightAsk whether two values are equal
function(argument)Call a function
object.method(argument)Call a function attached to an object
values[0], values[-1]Get the first or last item
a, b = pairUnpack two items into two names
def name(...):Define a function
return resultSend a result back to the caller
if condition:Run an indented block only if true
for _ in range(n):Repeat an indented block nn times
breakStop the nearest loop
values.append(item)Add one item to a list
raise ValueError(...)Stop and report an invalid value
assert conditionCheck an expectation
import numpy as npMake NumPy available as np

Ready enough is ready

You are ready to begin the phugoid computation when you can, with this appendix nearby:

  • run notebook cells in a deliberate order and recover with restart-and-run-all;

  • distinguish assignment from comparison and read a numerical expression;

  • call and define a small function, including a default argument;

  • follow an if branch and a for loop by hand for a few steps;

  • explain why a list grows with .append() and why it is later converted to an array;

  • recognize tuple unpacking and negative indexing;

  • use np.sin(), np.cos(), np.deg2rad(), np.isclose(), and np.isinf(); and

  • identify the Figure, Axes, data, labels, and grid in a Matplotlib cell.

That is recognition plus small, deliberate edits—not mastery. The phugoid lesson repeats these patterns in context, and later lessons will give you more practice.


Narrative content in this notebook is licensed under CC BY 4.0. Code cells are licensed under the BSD 3-Clause License.