Steven R. Woodruff - 25 January 2021 - CEE 303 - Computational methods
To start using Python 3 to solve engineering problems, you will need to understand some basic concepts.
Learning objectives:
As I understand, most of you have learned MATLAB in other classes. I assume that you understand how coding works in the abstract. In this document, my goal is to describe the specific syntax and style used in Python 3. I will emphasize concepts that are different from MATLAB and warn you of simple errors you might come across when you accidentally use MATLAB code in place of Python 3.
With a broad library of built-in functions that you have full access to (no hiding code, like with MATLAB), Python can do anything that MATLAB can accomplish. In fact, Python can be applied to a wider range of tasks than MATLAB. Python is also completely free (in the likely case where your employers do not want to pay thousands of dollars for MATLAB).
Reading all the documentation about Python and its applications, it can feel overwhelming and confusing. In this document, I will limit the concepts to those relevant to what you will need in the class. If there are more advanced coding techniques you must use, I will describe them to you in that lab module. If you are comfortable with Python, I encourage you to explore more complex techniques to improve your code, but know that the labs will not require these techniques.
One of the best features of Python is how readable the code is. In most instances, you should be able to understand what a piece of code does with little experience in coding.
Here are some of the basics of Python 3 syntax that we will use in the labs.
Commenting allows you to annotate your code without the computer reading your words as instructions. The goal of using commenting is to make your code as readable as possible or to temporarily remove lines of code.
In Python, commenting is applied to text after a #
symbol until the line ends. Examples include:
# Set values (indicate different sections of your code)
length = 2 # [m] (indicate the unit of a variable)
# old_length = 1 # (remove lines of code that you might use later)
Important note: Multi-line comments do not technically exist in Python 3. You can use a triple quote to assign a string literal that will not print in Spyder, but in Jupyter Notebook, this will be printed in the output. For example:
""" In Spyder, you can use triple quotes to comment out
multiple lines of text. However, in Jupyter Notebook,
the comment will be printed out. """
' In Spyder, you can use triple quotes to comment out\n multiple lines of text. However, in Jupyter Notebook,\n the comment will be printed out. '
Variable names can contain any letters, numbers, or underscores (_
). However, a variable cannot start with a number. For example:
# Valid variable names
my_name = 'Henry'
my_age = 34
x_0 = 0
_variable_name = 'This variable'
# Invalid variable names
1_value = 2
me_&_you = True
this.variable = 'will be read as a package and a module'
File "<ipython-input-3-3eb0ad07f08a>", line 8 1_value = 2 ^ SyntaxError: invalid decimal literal
Printing values to the console in Python is easy. Just use the print()
function. For example:
x = 'Hello, world!'
y = 23
print(x)
print(y)
Hello, world! 23
Python automatically assumes what data type a variable is, so you usually do not need to explicitly define a variable type.
Some variables we will use are:
-23, 0, 3929, 9
)1e-4, 3.14159, 2.
)3.
)'string', "my name is...", 'Hello, world!'
)"Yutong's favorite color is blue"
)True
or False
and can be used for conditional statementsTrue
and False
are capitalizedThere are other data types in Python, but we with either not use them, or I will explain them later.
You can always check what the data type of a variable is with the type()
function. For example:
integers = 3
floats = 2.4
strings = 'string'
booleans = True
print('An integer is ' + str(type(integers)))
print('A float is ' + str(type(floats)))
print('A string is ' + str(type(strings)))
print('A Boolean is ' + str(type(booleans)))
An integer is <class 'int'> A float is <class 'float'> A string is <class 'str'> A Boolean is <class 'bool'>
Math operators should look familiar:
a + b
a - b
a * b
a/b
Python has some unique operators, such as:
a ** b
(don't use ^
; this has a different meaning in Python)A @ B
(this is equivalent to taking the dot product of the two matrices)Logical operators compare two pieces of data and result in a Boolean (True
or False
). You are probably familiar with some of the logical operators in Python 3:
a == b
a != b
(This is different from MATLAB!)a < b
a <= b
a > b
a >= b
Logical operators are often used in conditional statements.
Another data type built into Python 3 is called a list. A list is a sequence of values that is mutable (you can change the values, remove values, add values). A list is denoted with square brackets. For example: my_list = [1, 'hi', True, 4.3, [1, 2]]
. Notice that lists can contain many different data types in one (including other lists).
To call an item from a list, you use square brackets in a different way. For example: my_list[0]
would be equal to 1
.
Note that in Python, the first item in a list or indexed data type is called with 0
. This is different from MATLAB!
Tuples are another data type built into Python. A tuple is similar to a list, except that it is immutable (once the tuple is created, you cannot change, add, or remove values). A tuple is denoted with parentheses. For example: my_tuple = (1, 'hi', True, 4.2, [1, 2])
.
As with lists, you can call items from a tuple using square brackets. For example: my_tuple[0]
would be equal to 1
.
Although you cannot change items in a tuple, you have the ability to extract values from it. A function with more than one output will give you a tuple.
Unlike MATLAB, indentations in Python have special meaning, and putting an indentation in the wrong place can produce a syntax error.
The amount that you indent does not matter to Python. The only thing that matters is that you stick to the number of spaces you choose for the entire script! Although you can choose the number of spaces in an indent, the convention is to use four spaces (programs like Jupyter and Spyder automatically indent by four spaces where necessary, by default).
Indentations are used to denote the beginning and end of loops, conditional statements, and functions.
Functions are pieces of code that take in values and usually output other values. In Python, a function must start with the key term, def
, and then the function name, and its inputs. The first line of a function declaration must end in a colon, :
.
After the colon is set, the function code is placed on the next line with an indentation.
The outputs of a function are declared using another key term, return
.
The function ends when the indentation stops. This is different from MATLAB which requires an explicit end
statement!
For example, the function $f(x, y) = x^2 + y^2$ can be coded with:
def f(x, y):
return x**2 + y**2
print(f(0, 1))
1
Functions can have intermediate code, as well. For example,
def say_hello(name):
statement = 'Hello there, ' + name
return statement
print(say_hello('Brian'))
Hello there, Brian
When a function has more than one output, the Python will combine the outputs into a single tuple. You can unpack these by listing the variables before calling the function. For example,
def my_function():
a = 'output_1'
b = 'output_2'
c = 'output_3'
return a, b, c
# Return tuple (a, b, c)
tuple_output = my_function()
print(type(tuple_output))
# Unpack tuple to return three strings
a, b, c = my_function()
print(type(a))
<class 'tuple'> <class 'str'>
Conditional statements are used to switch code on or off by examining a Boolean value. Conditional statements start with if
statements and then a logical equation or a Boolean variable. If the equation or variable is True
, then the code indented under the if statement will run.
You also have the option to code an elif
statement (elif
= else if). Here, if the if
statement is false, the elif
statement will evaluate the Boolean. This is different from MATLAB which uses elseif
!
If all previous statements are false, you can put an else
statement that will run the indented code underneath.
For example:
true_statement = True
# Another option:
# true_statement = 1 < 2
false_statement = False
# Another option:
# false_statement = 7 - 7 == 2
# Conditional (a)
if true_statement:
print('(a) The first statement is true.')
# Conditional (b)
if false_statement:
print('(b) The first statement is true.')
elif true_statement:
print('(b) The second statement is true.')
# Conditional (c)
if false_statement:
print('(c) The first statement is true.')
elif false_statement:
print('(c) The second statement is true.')
else:
print('(c) The third statement is true.')
(a) The first statement is true. (b) The second statement is true. (c) The third statement is true.
While-loops are loops that repeat code until some condition is True
. While-loops are useful for when you do not know how many iterations will be required until some condition is met. For example,
x = 10
loop_count = 0
while x > 1:
loop_count += 1
x -= 1
print('The number of iterations was ' + str(loop_count))
The number of iterations was 9
Be careful when using while-loop. If the condition you set to break the loop is never met, your code will run forever. For example,
x = 1
while x > 0:
x += 1
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) <ipython-input-15-704c30ea2fb0> in <module> 1 x = 1 2 while x > 0: ----> 3 x += 1 KeyboardInterrupt:
Notice that I had to interrupt the code using the "Interrupt the kernel" key. Otherwise, this loop would have run forever.
For-loops repeat lines of code a predetermined number of times. In a for-loop, you define an index extracted from a sequence of numbers (like a list or range).
A useful function to learn is range(n)
. This creates a range, which is like a list of integers (but you cannot use it like a list). Note that range(n)
will create n
iterations, but the last value will be n-1
since the first index is 0.
For example,
for i in range(10):
print(i)
0 1 2 3 4 5 6 7 8 9
You may also loop through values in a list using a for-loop.
colors = ['blue', 'green', 'red', 'purple']
for color_i in colors:
print(color_i)
blue green red purple
Often, once your code has calculated a value, you will want to print that value along with a description. For example, you might want the console to read The number of apples is 6
after running a calculation. You can add values to strings in a number of ways.
If your value is a string, you can simply add strings together. For example, 'Hello, ' + 'world!'
will print as 'Hello, world!'
.
If you want to put an integer or float into a statement, you can convert the value into a string using str(value)
and add the strings together. For example, 'My age is ' + str(54)
will print as 'My age is 54'
.
You can also use handles to place data into a statement. The advantage of handles are that they allow you to predefine what the data type is and the number of decimal points you want to print (if the data is a float). To do this, you write your string, and where the data should be, you place a handle using %d
for a decimal, %f
for a float, %0.2f
for a float with two decimal places (or whatever number you want, just replace the 2), %s
for a string. For example,
my_name = 'Jenny'
my_age = 27
my_gpa = 3.25
print('Hi my name is %s, my age is %d, and my GPA is %0.2f.' % (my_name, my_age, my_gpa))
Hi my name is Jenny, my age is 27, and my GPA is 3.25.
If you do not know how a function works, you can always find the answer using the help()
function. By typing help(function_name)
, the documentation for the function will appear in the console.
help(min)
Help on built-in function min in module builtins: min(...) min(iterable, *[, default=obj, key=func]) -> value min(arg1, arg2, *args, *[, key=func]) -> value With a single iterable argument, return its smallest item. The default keyword-only argument specifies an object to return if the provided iterable is empty. With two or more arguments, return the smallest argument.
You can also find answers online by searching for the function name. For example, Python 3 min
.
Python on its own has a relatively limited library of functions. For example, there is no sine function built into Python 3. People have developed packages that contain other functions, which you can use in Python. Think of a package as a folder in your directory. That folder is filled with functions such as sin()
which you can access if you tell Python that you want to use that folder and function.
To open up a package, you must import it using import
. For example, import numpy
will tell Python that you plan on using the functions in the package NumPy. You can access those functions by typing numpy.sin()
. The period in the code means that you want the sin()
function within numpy
(this is like telling Python you want it to look in the numpy
package for the sin()
function).
Modules are a subset of packages, sort of like a subdirectory in the package folder. Modules are a convenient way to organize code. For example, NumPy has a module called linalg
that stores all its linear algebra functions. You can call a function in a module in a similar way using periods. For example, numpy.linalg.norm()
calls a function that calculates a vector/matrix norm within the linear algebra module within the NumPy package.
Now, it might seem difficult having to type all these packages and modules all the time. You can get around this by renaming packages and modules with the import numpy as np
. Here, np
is the shortened version of numpy
. So with this, to access the sine function, you simply need to write, np.sin(x)
.
It is conventional to import the packages and modules you plan on using at the beginning of your code. For example,
import numpy as np
import numpy.linalg as npl
x = [0, np.pi/2]
y = np.sin(x)
norm = npl.norm(y)
print(norm)
1.0
In this lab, we will use the NumPy package in almost every project. NumPy contains a wide variety of useful functions, such as trigonometric functions. A full list of NumPy's built-in functions can be found in its documentation, https://numpy.org/doc/1.19/.
Note that it is a convention to import numpy as np
, and most people use this convention.
Some useful functions within NumPy include:
np.sin(x)
, np.cosh(x)
, np.arctan(x)
)np.pi
, np.exp(1)
)NumPy comes with the Anaconda package, so you will not need to install it on your computer.
If you are familiar with MATLAB, you know that MATLAB uses 2D arrays to store data (like a matrix). In Python, you can create arrays with NumPy. Unlike MATLAB, NumPy arrays can be truly n-dimensional.
A 1D array is a sequence of numbers with only one dimension (it is not a vector that you can transpose, but you can reshape a 1D array to be a vector). 1D arrays are useful for storing data like plotting domains and output values. 1D arrays are similar to lists, except that only one data type can be stored on an array at a time.
The benefit of using arrays versus lists is that arrays use less memory (since there can only be one data type), and you can easily reshape arrays to perform linear algebra computations.
To create a 1D array, you can use the np.array()
function. For example,
x = np.array([1, 2, 3, 4, 5, 6])
print(x)
print(type(x))
[1 2 3 4 5 6] <class 'numpy.ndarray'>
Note that Python interprets NumPy array types as ndarray
, which is shorthand for n-dimensional array.
The input for the np.array()
function is a list.
The np.array()
function can also create 2D or n-dimensional arrays. To do this, you nest the lists. For example,
x_2D = np.array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
print(x_2D)
[[1 2 3] [2 3 4] [3 4 5]]
This 2D array will behave like a matrix.
NumPy contains useful array functions, such as np.zeros()
and np.ones()
which create an array of zeros or ones, respectively. You can use these functions to create arrays with constant values or values you plan on changing later. For example, to create an array with six entries of 2, you can code:
array_of_twos = 2*np.ones(6)
print(array_of_twos)
[2. 2. 2. 2. 2. 2.]
In this lab, you will use plots to show your results and interpret data. The Matplotlib package with PyPlot module allow you to do this.
To import the package and module, it is convention to write, import matplotlib.pyplot as plt
.
PyPlot contains useful functions that control the plots you will generate. For example, plt.plot(x, y)
produces a line plot with data points in the x- and y-axes.
The best way to learn how to use PyPlot is to see examples. See the example project reports for this. Here is one example,
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2*np.pi, 100) # Array of x-values
y = np.sin(x) # Array of y-values
plt.plot(x, # Plot the x-values
y, # Plot the y-values
'--r', # Line type (-- = dashed) and color (r = red) [Optional]
linewidth=3) # Specify the line width (3 pts) [Optional]
plt.xlim((0, 2*np.pi)) # Specify the min and max of x-values plotted (tuple input)
plt.ylim((-1.1, 1.1)) # Specify the min and max of y-values plotted (tuple input)
plt.xlabel('x [rad]') # Label the x-axis
plt.ylabel('y') # Label the y-axis
plt.title('Example plot') # Label the title
plt.show() # Show the plot
Note that I created the domain, $x$, using a NumPy function, np.linspace(start, stop, n)
, where you define the first value (start
), the last value (stop
), and the number of points in the array (n
). This is a useful function to quickly make a domain.
The philosophy that underlies Python is that code is read more often than it is written; as such, Python code is designed to be readable. We can see this with straight-forward function naming.
Another dimension of readable code is style. Style is the choices you make when writing code. Remember that you have a lot of freedom when writing Python. The rules for choosing variable names are limited, but style helps you choose names that are consistent and easy to read.
The style guidelines adopted by most Python coders is explained in PEP 8 (see https://pep8.org/). PEP 8 provides a list of guidelines that will make your code easier to read. It is important to know that the PEP 8 guidelines are not required and should be ignored under certain circumstances. The ultimate goal is always readability of code. If the company you work for uses a special type of variable name, it is better to be consistent with that style than to use another.
Here are some of the important PEP 8 guidelines you should use:
my_variable
, solution_a
, mean_value(x)
np.array([1, 2, 3])
is better than np.array([1,2,3])
Know that in Spyder, there is an option for automatic PEP 8 detection. Spyder will read your code and tell you if you are violating a PEP 8 rule. To access this, open Spyder; on the top toolbar, hit Tools > Preferences > Completion and linting > Code style > Enable code style linting.