My Python notes

1 Something about print

syntax explanation
print(str1, str2, sep = "") print strings separately
print(str1 + str2) print strings as one string
print(f'{my_var}') f-string interpret what inside the {}
print('%type' %my_var) %d: integer; %f: float; %s: string; %b: binary; (doc)
print(\n) print use escape characters
print(f'{my_var:n[type]}') print the variable at a certain length
{:<}, {:>}, {:^} left aligned, right aligned, centred

2 Import modules

  • Import a module as a separate namespace
import numpy as np
print(np.cos(np.pi))
  • Import something from a module into the main namespace
from numpy import cos, pi
print(cos(pi))

3 Variables and objects

type() : check data types.

  • Numeric: int, float, complex;

  • Sequence: str, list, range, tuple

  • Boolean

  • Set

  • Dictionary

  • number objects and string objects

3.1 Strings

syntax explanation
my_str[i] returns the \(i+1\)th character in string
my_str[-i] returns the \(i\)th from the end
len(my_str) the length of the string
max(my_str), min(my_str) alphabetically
sorted(my_str) or my_str.sort() from smallest to largest
my_str.capitalize() capitalize the first letter of the string
my_str.split() split the string

3.2 Booleans

Operators:

syntax explanation
and, or, not logical operators
==, <, <=, != comparison operators

3.3 Numbers

Floating points numbers: 1.0e-6 is \(1 \times 10^{-6}\).

syntax explanation
+, -, *, / addition, subtraction, multiplication, division
** exponentiation
// integer division
% modulus; the remainder of a deviation

math.isclose(n1, n2, rel_tol=1e-6): Boolean variable if n1 and n2 is close.

3.4 Type casting

int(), float(), str().

bool(0) and bool('') are false.

3.5 List

List can contain almost any other object.

my_list = ['my', 1, 4.5, ['you', 'they'], 432, -2.3, 33]
emplist = []
[sth] * n  # [sth, s]
print(list_1 + list_2)
print('hellow'+'world')    # "helloworld"
my_list.append('extar')    # add an item to the end of a list
print(my_list[3][1])       # the outcome is "they"
print(sorted(numberlist))  # sort a list
print(12 * my_list)        # create a list with 12 repetition of my_list
print('you' in my_list[3]) # check if something is in a list

Useful tools:

syntax explanation
len(my_list) the length of the list
my_list.append('a new element') add a new element to the list

Slicing:

a = [2, 5, 4, 8, 8]
print(a[1:3]) # the 2nd and 3rd | [5, 4]
print(a[2:])  # the 3rd to the last | [4, 8, 8]
print(a[:-2]) # the 1st to the 3rd from the last | [2, 5, 4]
syntax explanation
my_list[start:stop] from start to stop-1 共stop-start个
my_list[start:] from start to len(l)-1
my_list[:stop] from 0 to stop-1
my_list[start:stop:step] from start to stop-1, with increment step
my_list[::step] from 0 to len(l)-1, with increment step
my_list[::], my_list[:] all the elements
  • If j \(=\) i, then a[i:j] and a[i:j:k] are empty lists, for any value of k.
  • If j \(<\) i, then a[i:j] and a[i:j:k] are empty lists, for positive values of k.

4 if statements

if my_condition:
    [some instructions]

my_condition is a Boolean object.

if cond_1:
    [some instructions]
elif cond_2:
    [other instructions]
else:
    [other instructions]

5 Loops

5.1 for loops

for i in my_seq:
	[some instructions]
  • ranges: a sequence type
syntax explanation
range(j) \(0\), \(1\), \(2\), ..., \(j-1\); 共\(j\)个.
range(i, j) \(i\), \(i+1\), \(i+2\), ..., \(j-1\); 共\(j-i\)个.
range(i, j, k) \(i\), \(i+k\), \(i+2k\), ..., \(i+m\); \(i+m \leq j-1\).

5.2 while loops

while my_condition:
    [some instructions]

Use break to exit the loop conditionally:

while my_condition:
    [some instructions]
    if my_condition:
        break

6 Defining function

def my_func(inputs):
    [function body]
    return outputs

Outputs can be variables separated by commas.

Docstrings of functions:

In general, a docstring should consist of:

  • a brief (1 or 2 sentences) description of what the function does,
  • a description of all input arguments and their type,
  • a description of all outputs and their type.

def some_func(some_input):
	'''
	a one-sentence description of the function
	
	Input:
	    some_input (type): description.
	        
	Output:
	    some_output (type): description.
	'''
    
    # the main body
    
    return your_output

Use help(some_func) to see the function's docstring.

7 Debugging and troubleshooting

7.1 Built-in exception types:

  • IndexError: a sequence subscript is out of range. r instance, here, we're trying to access my_list[4], but my_list only has elements up to my_list[3].
  • NameError: the variable referred to does not exist -- there is no box in memory with this label. This often comes up when you mistype a variable name.
  • SyntaxError: the code is not syntactically correct -- it is not valid Python, so Python doesn't know how to interpret it.
  • TypeError: a very common error to see when learning Python! This means that an operation or a function is applied to an object of the wrong type
  • ValueError: raised when an operation or function is applied to an object with the right type, but an invalid value. For example, the int() function can cast a string to an integer, if the string can be interpreted as a number.

7.2 Raise error

if Cond:
	raise ValueError('Error massages')

Catch errors:

try:
    # do something
except:
    # if the bit in "try" produces a runtime error

Use eval() to evaluate operations:

# Put all operations in a list, as *strings*
operations = ['...', '...', ...]

# Use eval() to try all of them, print('error')
# if they don't work
for op in operations:
    try:
        eval(op)
    except:
        print('error')

7.3 Code review

  • Is the code easy to read and to understand?
  • Are there any bugs? Does the code produce the intended result, without errors?
  • Could this code easily be re-used or adapted in other contexts?
  • Is the implementation efficient? Is there too much data stored in memory that we don't need? Is there another way to program this, which takes less time to compute?

7.4 Interact with input() function

your_inpt = float(input('Please enter something and press enter:'))

8 Namespace and scope

Namespace: a set of names, together with the objects they refer to.

The function's namespace is deleted once the function exits (that is, once the command func() has finished executing).

Scope: a part of your code from where you can access a certain namespace. local scope and global scope.

9 N-dimensional array: ndarray type

np.array(): create an array; takes a list as an input and returns an array where the rows are the elements of the list. (numpy.array — NumPy v1.21 Manual)

1-D Numpy arrays are similar to lists.

import numpy as np

# create a vector
my_vec = np.array(my_list)

# create a matrix
my_mat = np.array(a_list_of_lists, dtype=None)
# dtype is for specifying the type of its elements.

9.1 Special arrays

  • create a \(n \times p\) matrix of zeros
mat_zeros = np.zeros([n, m])
  • create a vector of ones of length \(n\)
vec_ones = np.ones(n)
  • create an \(n \times n\) identity matrix
id_n_mat = np.eye(n)
  • create a \(n \times p\) matrix of pseudo-random numbers between 0 and 1, sampled from a uniform distribution
randm_mat = np.random.random([n, p])

randm_mat = np.random.random([n, p]) * (b - a) + a  # sampled from a unif(a, b)
  • create a 1D array with a range from m to n with step \(p\)
mat_1d = np.arange(m, n, p)
  • retrieve the dimensions of an array, as a tuple; a property of ndarray objects
print(mat_zero.shape)  # no brackets for .shape

.reshape() take one input argument and reshape the array.

eg. To construct the matrix

\[M = \begin{pmatrix} 0.1 & 0.2 & 0.3 \\ 0.4 & 0.5 & 0.6 \\ 0.7 & 0.8 & 0.9 \end{pmatrix} \]

# First way: giving the list of rows explicitly
M1 = np.array([[0.1, 0.2, 0.3],
            [0.4, 0.5, 0.6],
            [0.7, 0.8, 0.9]])
print(M1)

# Second way: using range() and .reshape()
# Note that range() returns a sequence, which we can therefore use
# directly as the input argument for np.array()
M2 = 0.1 * np.array(range(1, 10)).reshape((3, 3))
print(M2)

# Third way: using np.arange() and .reshape
M3 = np.arange(0.1, 1, 0.1).reshape((3, 3))
print(M3)

9.2 Element-wise operations

element-wise (+, -, *, /, **) operations can be used between:

  • two arrays of the same size
  • an array and a scalar

np.dot() can be used as *.

9.3 Matrix operations and linear algebra

syntax explanation
np.matmul(A, B) or A @ B \(AB\) (matrix products)
A.T or A.transpose() \(A^T\) (transpose)
np.matmul(A, v) or A @ v \(Av\)
np.matmul(v, B) or v @ B \(v^TB\)
np.matmul(v, v) or v @ v \(v^2\)

9.4 matrix operations using sub-module linalg

(Linear algebra (numpy.linalg) — NumPy v1.21 Manual)

Prefix with np.linalg. when using.

syntax explanation
np.linalg.eigvals(A) eigenvalues of a matrix (\(Ax = \lambda x\))
eig_val_A, eig_vec_A = np.linalg.eig(A) eigenvalues and right eigenvectors
Q, R = np.linalg.qr(A) Q-R matrix decomposition
U, S, V = np.linalg.svd(A) singular value decomposition
np.linalg.inv(A) \(A^{-1}\) (inverse)
np.linalg.det(A) $
np.linalg.solve(A, b) Solve \(Ax = b\) for \(x\)

9.5 Indexing and slicing Numpy arrays

v[i] is the \(i+1\)th element of the vector v.

A[i, j] is the element in the \(i+1\)th row and \(j+1\)th column of the matrix A.

X[i, j, k, h, ...] is used to index elements for tensors in higher dimensions.

eg. an example of how you can use Boolean indexing to extract elements of an array which fulfill certain conditions.

# Create a random number generator
rng = np.random.default_rng()

# Create a random 3x5 matrix of integers between 1 and 10
A = rng.integers(1, 11, size=[3, 5])
print(A, '\n')

# Create a Boolean array the same shape as A, with True where the corresponding
# elements of A are smaller than 5, and False elsewhere
A5 = A < 5
print(A5, '\n')

# Use A5 to return all elements of A smaller than 5 (in a 1D array)
print(A[A5], '\n')

# Display the rows of A starting at row 1, and columns ending at column 2
print(A[1:, :3], '\n')

# Display the elements of that sub-matrix which are smaller than 5
print(A[1:, :3][A5[1:, :3]], '\n')

# Reassign all elements of A which are greater than or equal to 5 with the value 100
A[np.logical_not(A5)] = 100
print(A)

10 Basic reading and writing data from/to an external file

10.1 Using open() and .close()

myfile = open('mytextfile.txt', mode='r')  # assign the opened file as a file object `myfile`
contents = myfile.read()  # save the read file as `contents`
myfile.close()  # close `myfile`
mode description
r default, for reading
r+ for both reading and writing
w for writing only
w+ for both writing and reading
... ...

10.2 Using the with statement

Use the with statement to automatically closes the file when the block ends.

Use the .readline() method of file objects to read the file line by line. .readlines() reads all lines in at once. The return is a list.

with open('mytextfile.txt', 'r') as myfile:
    lines_content = myfile.readline()
	# read the first line
    
print(lines_content)

Read line by line:

# first approach: using 'readline'
with open('mytextfile.txt','r') as myfile:
    # Initialise an empty list to store the lines
    all_lines = []

    # if line is empty, the end of file is reached 
    while True:
        # use readline to read the next line...
        line = myfile.readline()
        if not line:
            break
        all_lines.append(line)
        
print(all_lines)

# 2
with open('mytextfile.txt','r') as myfile:
    all_lines = myfile.readlines()
    
print(all_lines)
print(all_lines[1])

10.3 Writing to a file

Create a new file and open it by using open() with the argument 'w'.

Use the .write() method of file objects to write into the file.

with open('mytextfile_new.txt', 'w') as mynewfile:
    mynewfile.write(text1 + '\n')
    mynewfile.write(text2 + '\n')

11 Plotting with matplotlib.pyplot

11.1 Basic of plots

Import the plotting tools frommatplotlib.pyplot with

%matplotlib notebook  # a notebook-wide setting for jupyter notebook

import matplotlib.pyplot as plt

%matplotlib inline  # toggle back to the default behaviour

A basic plot can be generated using

plt.plot([x], y, [fmt], [x2], y2, [fmt2])

fmt can be:

The x-axis with \(n\) points from \(s\) to \(e\) can be created as

x = np.linspace(s, e, n)

Use plt.show() to print the plot.

eg. plot \(y = x sin(x)\).

import numpy as np

%matplotlib notebook
import matplotlib.pyplot as plt

# Create an x-axis with 1000 points
x = np.linspace(0., 2*np.pi, 1000)

# Evaluate the function at all these points
y = x * np.sin(x)

# Create the plot and display it
plt.plot(x, y, 'k-')cv,
plt.show()

Figures and axes are objects in python.

plt.subplots() is used to create a new figure object.

fig, ax = plt.subplots(m, n, [figsize])  # figsize=(a, b)
# like `par(mfrow = c(m, n)) in r

Use .plot() as a method of the Axes object

ax[i, j].plot(x, y, [fmt])  # plot on  row, jth col

Use .subplots_adjust() to adjust the layout of subplots

plt.subplots_adjust(hspace=0.5, wspace=0.5)
parameters description
left The position of the left edge of the subplots, as a fraction of the figure width.
right The position of the right edge of the subplots, as a fraction of the figure width.
bottom The position of the bottom edge of the subplots, as a fraction of the figure height.
top The position of the top edge of the subplots, as a fraction of the figure height.
wspace The width of the padding between subplots, as a fraction of the average Axes width.
hspace The height of the padding between subplots, as a fraction of the average Axes height.

11.2 Customising plots

11.2.1 Setting plot axis properties

  • Axis limits: .set_xlim() and .set_ylim() methods of Axes objects.
my_ax.set_xlim([start, end])
my_ax.set_ylim([start, end])
  • Axis labels: .set_xlabel() and set_ylabel() methods of Axes objects.

    my_ax.set_xlabel(r"$x$ axis", fontsize=12)
    my_ax.set_ylabel(str, [kwargs])
    

    kwargs: text properties controling the appearance of the label.

  • Adding a legend: ax.legend() would label all curves of the plot in the ax. But the label should be set inside the .plot() using lable=argument, and can contain \(LaTeX\) code.

# .legend() will use the "label" arguments for each curve
ax.legend(loc='lower right', fontsize=14)

loc: combinations of 'center', 'upper', 'lower', 'left', 'right'; and 'best'

matplotlib.legend — Matplotlib 3.4.3 documentation and 5 more pages

  • Adding grid lines: plt.grid()

12 SciPy

12.1 Interpolating some noisy data

import scipy.interpolate
import scipy as scp

# Make an interpolating function - this one goes through all of the 
# data points, and joins them with a piecewise cubic function:
scp.interpolate.interp1d(x, y, kind='cubic')

# Now fit a spline using a different function that takes a smoothing 
# parameter s, this spline won't go through all of the points but will 
# look smoother:
f_smooth = scp.interpolate.UnivariateSpline(x, y, s=4)

#  return a function object

12.2 Summary statistics, reading a file

import numpy as np
import scipy.stats as stats

# basic summary statistics:
stats.describe(germany)

# Find the 5% and 95% percentile locations:
np.percentile(germany, (5, 95))

# Find the Pearson's and Spearman's correlation coefficients
# between two columns:
print(stats.pearsonr(germany, denmark))
print(stats.spearmanr(germany, bulgaria))

# mode, count
mode, count = stats.mode(bulgaria)
# Display the results in a table, highlight correlated columns
colourmap = plt.cm.get_cmap('Greens')   # get a colourmap function to map colours to numbers
colours = colourmap(pearson_coeffs)

fig, ax = plt.subplots(1, 1, figsize=(7, 2))
ax.table(cellText=pearson_coeffs,
         rowLabels=countries,
         colLabels=countries,
         cellColours=colours,
         loc='center',
         cellLoc='center')
ax.axis('tight')
ax.axis('off')
plt.show()
# create a linear regression object using stats.linregress
regr = stats.linregress(germany, denmark)

12.3 Optimisation

scipy.optimize.linprog()

from scipy.optimize import linprog

A = np.array([[6, 3],
              [3, -1],
              [1, 0.25]])

b = np.array([40, 0, 4], dtype=float)
c = np.array([-30, -10], dtype=float)

solution = linprog(c, A, b)

results = A @ solution.x

13 Tuples

Tuples are immutable lists.

a_tuple = (4, 6, -2, 4, 0, 0)

# nest tuples in lists
b_tuple = [(1, 2), (), e, ('this', 'maybe')]

A useful feature is that variables can be unpacked from a tuple, meaning that we can, for example, assign the value of each element in a tuple to a different variable, in one line:

u, v, w = (3.4, 1, 'friday')
print(f'{u}, {w}')

# Swap 2 values
u, w = w, u
print(f'{u}, {w}')

Note: Lists, tuples, and strings are examples of sequences, meaning that their elements (for a str, its characters) are ordered, and indexed by a number representing their position. Index slicing can also be used on any sequence type.

14 Dictionaries

A Python dictionary is a set of *key-value* pairs. Dictionary values can be any object (e.g. numbers, sequences, Booleans, even other nested dictionaries).

scores = {'Alice': 80, 'Bob': 64, 'Charlie': 72}
print(scores['Bob'])

print(scores)                # Print the dictionary object
print(list(scores.items()))  # Print dict items as a list of tuples
print(list(scores.keys()))   # Print all keys in a list
print(list(scores.values())) # Print all values in a list

Outputs:

64
{'Alice': 80, 'Bob': 64, 'Charlie': 72}
[('Alice', 80), ('Bob', 64), ('Charlie', 72)]
['Alice', 'Bob', 'Charlie']
[80, 64, 72]

We can add and modify dictionary entries, or check whether a key exists in a dictionary:

Create an empty dictionary
my_dict = {}

Add 3 new items -- note that we don't need to append with dictionaries.

my_dict['First item'] = (4, 5)
my_dict['Second item'] = 'blue'
my_dict[(0, 1)] = True
print(my_dict)
print(len(my_dict))

Modify one item.

my_dict['Second item'] = 8.77
print(my_dict)

Check if a key (not a value!) exists in the dictionary.

print((0, 1) in my_dict)
print((4, 5) in my_dict)
{'First item': (4, 5), 'Second item': 'blue', (0, 1): True}
3
{'First item': (4, 5), 'Second item': 8.77, (0, 1): True}
True
False

Uses the .items() method to loop over a dictionary and return a list of tuples.

my_dic.items()

15 Compreshensions

A combination of sequence, for loop and if statement. To construct a new sequence from an old sequence, with operation for each element of the original sequence. Can be nested.

[experession for item in seq if condition]
[expression1 if condition else expression2 for item in seq]

The same for dictionaries, tuples, etc.

# Flatten a matrix to a list -- here, "i" is a list of the rows of A
A = np.random.randint(1, 10, size=[3, 3])
print(f'A =\n{A}\n')
print([j for i in A for j in i])

16 Designing algorithms

16.1 Recursion

A procedure or function that calls itself in order to provide an answer.

Note that, just like in the mathematical expression, we need to specify the initial value explicitly -- otherwise, we would go on forever!

def fib_rec(p, q, n):
    '''
    Return the nth element of the (p,q)-Fibonacci sequence.
    
    Input:
        p (int), positive integer, first coefficient
        q (int), positive integer, second coefficient
        n (int), positive integer
        
    Output:
        Fn (int), the nth element of the sequence, defined by
        F(n) = pF(n-1) + qF(n-2).
    '''
    if n == 1 or n == 2:
        return 1
    else:
        return p*fib_rec(p, q, n-1) + q*fib_rec(p, q, n-2)

print(fib_rec(1, 1, 15))
print(fib_rec(6, 4, 10))
print(fib_rec(2, 1, 35))

16.2 A process for problem-solving

The Algorithm Design Manual

  • What is the end goal of the problem? What should the final result look like?
  • What data do I have? What object types are best suited to store/handle which data?
  • What should the rough structure of the algorithm be? What essential techniques are needed – loops/decisions, for/while...
  • Can I break the problem down into sub-tasks?
  • Does it have a recursive structure – can I do a little bit of it, and leave myself with a problem that looks almost the same?
  • How do I know when I get an answer – can I check the answer? (sometimes answers that are hard to get are easy to check!)

7-step guide to problem-solving

image.png

  • Step 1: Work an Example

    The first step is to work one instance of the problem by hand.

  • Step 2: Write Down What You Did

    The second step is to write down precisely what was done in Step 1.

  • Step 3: Generalize

    In Step 3, the student should generalize from the specific values they used in Step 1 to any values of the parameters.

    Students who get stuck here should repeat Steps 1 and 2 with different parameters
    to help see the pattern.

  • Step 4: Test by Hand

    Step 4 is to test your algorithm by hand. Using different values for the parameters.

  • Step 5: Translate to Code

    Any step that is too complex to translate into one or two statements should become its own function: students repeat the Seven Steps for that function and call it in this algorithm.

  • Step 6: Test

    Step 6 is to test the program, by running actual test cases on the code. If a
    test case fails, students proceed to Step 7.

  • Step 7: Debug
    Step 7 is to debug failed test cases.

posted @ 2021-10-08 21:36  ZZN而已  阅读(42)  评论(0编辑  收藏  举报