Python fundamentals
J/K or →/← jump between sections
Variables are names for values
Step through: a name appears when it is first assigned, and changes when assigned again.
Built-in names can be overwritten by accident
print = 1
print("123")
del print # back to the built-in
print("123")
Numbers: /, //, %
/ always gives a float. // is how many whole rows fit, % is what is left over.
Every value has a type
int
2, 13 // 2, a ** 2whole numbers, exact
float
13 / 2, 0.1, 1e-3decimals, not exact:
0.1 + 0.05 → 0.15000000000000002bool · str
True, 5 > 4, 1 == 1.0"text", 'H' == 'H'comparisons give booleans
type(x) tells which one.
Strings
Text in quotes. Characters are numbered from 0 from the left, and from −1 from the right.
formula = 'C2H5OH'
Operators and methods
'Hello ' + 'World'
'Hello' + str(1), 'A' * 5
'H' in formula, formula.count('H'), formula.find('OH')
'Hello' + 1
Text and numbers do not mix: convert first with str(1) or int('1').
split turns one string into a list of strings
line = 'H, C, N, O, Fe'
line.split(', ')
line.upper(), line.lower(), len(line)
f-strings: values inside text
After the colon comes the format: alignment, width, decimals. Build one and watch the output cells.
n = 4
mass = 18.015
print(f'Water has {n} atoms and mass {mass:.1f}')
Files
with opens the file and closes it for you. readlines() gives one string per line, newline included.
with open('test.txt', 'w') as f:
f.write('123\n')
f.write('456')
with open('test.txt') as f:
lines = f.readlines()
lines
'w' = write (creates or overwrites). No second argument = read.
with open('pyridine.xyz') as f:
lines = f.readlines()
print(lines[0])
print(lines[2])
lines[2].split()
print adds its own newline, so a line that ends with \n prints with a blank line after it. split() without argument splits on any whitespace. Everything is still text: float('-0.18…') makes a number.
Lists and tuples
A list is an ordered, changeable collection. Click the statements in order.
elements = ['H', 'C', 'N', 'O', 'Fe']
Indexing and slicing work exactly as for strings
A list can mix types; a tuple is a list you cannot change
mixed = ['Hola', 123, True, 4.5]
for item in mixed:
print(item, type(item))
t = ('H', 1, 1.008)
t[1] = 2
Round brackets, fixed content. Reading t[1] is fine.
Two names, one list
b = a does not copy. Both names point to the same object; changing it through one name is visible through the other.
for, range, enumerate
The loop variable takes each value of the collection in turn. The indented block runs once per value.
range makes the numbers to loop over
stop is never included. range(5) means range(0, 5, 1).
Index and value together
Exercises 1 and 2
1. Lists
With elements = ['H', 'C', 'N', 'O', 'Fe']:
- Print the first and the last element.
- Append
'S', remove'N', print the length of the list. - Print the list sorted alphabetically; the original list must stay unchanged.
2. Formatted table
Print the elements as a table with two right-aligned columns of width 5 and 8, using enumerate and f-strings:
Index Element
0 H
1 C
Dictionaries: key → value
Look up by name instead of by position. Click the statements in order.
carbon = {'symbol': 'C', 'mass': 12.011, 'number': 6}
The dictionary used in the exercises and later today:
masses = {'H': 1.008, 'C': 12.011, 'N': 14.007, 'O': 15.999, 'Fe': 55.845}
Building a dictionary in a loop
Exercise 3: Dictionaries
Calculate the mass of water, ['H', 'H', 'O'], with a for loop and masses.
Conditions: if / elif / else
Conditions are tested top to bottom; the first true one wins, the rest are skipped.
Comparisons and and, or, not
== compares values, is compares identity
Empty things count as False
text = ''
if text:
print('not empty')
else:
print('empty')
Also false: 0, [], {}, None. Note '0' is a non-empty string.
Exercise 4: Conditions
Loop over masses and print each element as light (mass below 10), heavy (above 50) or medium:
H light C medium N medium O medium Fe heavy
while: repeat as long as a condition holds
The condition is re-checked before every pass. Something inside must move it towards False.
Exercise 5: Loops
Calculate the sum of all even numbers from 2 to n (included), first with a for loop over range, then with a while loop.
n = 10 # for loop ... print(total) # while loop ... print(total)
30 30
Comprehensions: a loop that builds a list in one line
Hover a part to see where it goes.
for i in range(10): doubles.append(i * 2)
[i * 2 for i in range(10)]
for x in range(1, 11): if x % 2 == 0: squares.append(x**2)
[x**2 for x in range(1, 11) if x % 2 == 0]
The same for dictionaries
name_lengths = {}
for element in elements:
name_lengths[element] = len(element)
{element: len(element) for element in elements}
positions = {}
for i, element in enumerate(elements):
positions[element] = i
{element: i for i, element in enumerate(elements)}
Exercise 6: Comprehensions
In one line each: the list of squares of the even numbers from 1 to 10, the list of symbols in masses heavier than carbon,
and the dictionary of the heavy elements only (mass > 12) with a dictionary comprehension.
Reading an error message
Read the last line first: the kind of error and what went wrong. Then find the arrow: where.
1 / 0
print(undefined_variable)
Usually a typo, or a cell that was not run yet.
Functions
A function gets its own box of variables while it runs. return hands a value back; print only shows it.
print is not return
Docstrings: a comment the function carries with it
def product(a, b):
"""Return the product of a and b."""
return a * b
product?
A string as the first line of the body. ? in Jupyter (or help(product) anywhere) shows it; this is what you see for every library function too.
A loop inside a function
Several values come back as a tuple
def get_even_numbers(n):
numbers = list(range(0, n, 2))
return len(numbers), numbers
count, values = get_even_numbers(10)
count, values
Two names on the left, two values on the right: unpacking.
Scope: what lives where
Names created inside a function disappear when it returns. Constants go at the top, in CAPITALS.
energy_kcal
def set_value():
global value
value = 5
set_value()
value
global writes into the outer box. Legal, rarely a good idea: return the value instead.
Default and keyword arguments
Positional arguments fill parameters left to right. Keywords go by name. Missing ones take their default.
*args collects extra positional, **kwargs extra keyword arguments
Recursion
A function may call itself. Each call gets its own box; they pile up, then unwind.
Exercise 7: Functions
1. Write molecular_mass(symbols) that returns the mass of a molecule given as a list of symbols, using masses.
print(molecular_mass(['H', 'H', 'O'])) print(molecular_mass(['C', 'O', 'O']))
18.015 44.009
2. Write describe(symbol, charge=0) that prints the symbol and its charge.
describe('O')
describe('Fe', charge=3)
O, charge 0 Fe, charge 3
Scripts and sys.argv
A .py file is run from the terminal. The words after python arrive as a list of strings. Edit the command line.
# argv.py import sys print(sys.argv)
The homework template
# homework/hw1/count_atoms.py
import sys
if len(sys.argv) > 1:
filename = sys.argv[1]
else:
print("Filename not provided!")
exit()
# filename is a string: open it, count the atoms
Everything in sys.argv is text. sys.argv[0] is the script itself.
Homework 1
by Slack, end of Tue 13 Oct1. Fibonacci: the n-th term, with a loop and with recursion.
2. Read the book sections "Additional notes on I/O" and "Using libraries" (sys, os, argparse).
3. count_atoms.py: count the atoms of each element in an XYZ file.
C 34 O 4 N 4 Fe 1 H 30