python22.sci2u.dk Active sci2u
Loading...
Login
Prefer latest booklet Prefer latest booklet Login
Link to booklet is copied to clipboard!
Saved to booklet!
Removed from booklet!
Started capturing to booklet.
Stopped capturing to booklet.
Preferring latest booklet.
No longer prefers latest booklet.
Entered edit mode.
Exited edit mode.
Edit mode

Click on the booklet title or a chapter title to edit (max. 30 characters)


Python book

Basic Python
1.1 Packages
1.2 Python as pocket calculator
1.3 Variables
1.4 Variable types
1.5 Lists
1.6 Changing lists
1.7 List comprehensions
1.8 Tuples
1.9 Dictionaries
1.10 Strings
1.11 Formatted printing
1.12 Loops
1.13 Lambda-functions I
1.14 Lambda functions II
1.15 Functions I
1.16 Functions II
1.17 Boolean
1.18 Boolean expressions
1.19 Branching
Numerical Python Plotting with Matplotlib Advanced Python Add Chapter..

Basic Python

1.1 Packages

The python kernel starts out rather empty with only few built-in functions and variables. In this course we shall be using stuff from three important packages:
  1. numpy that handles lists and matrices of numbers efficiently and provides access to a range of algebraic functions
  2. matplotlib that allows for plotting and animating any calculated result.
  3. scipy that provides various python functions for functional analysis, solving differential equations, and much more.
In order to use the packages, you may start any Jupyter notebook with a cell importing all or parts of them. It may look like this:
import numpy as np
import matplotlib.pyplot as plt
from scipy.linalg import norm
from scipy.optimize import fsolve
Once the cell has been executed, you have access to all content in the numpy and matplotlib packages and to two specific functions, norm and fsolve from the linear algebra and optimization modules of the scipy package.
Owing to the as np and as plt declarations, the functions from the first two packages are accessed with preceding np. and plt. name tags like this:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.linspace(0,3.14,50)
y = np.cos(x)
ax.plot(x,y,color='red')
The np.linspace and np.cos are numpy functions, while plt.subplots and ax.plot are matplotlib functions. When the cell is run, it incidentally plots for :

Figure 1

Declaring as np and as plt serves to reduce the amount of typing you have to do. If you leave them out, writing just import numpy and import matplotlib.pyplot you would have to write some lengthier function names: numpy.linspace, numpy.cos, and matplotlib.pyplot.subplots in the above example.
The functions in the optimize module of the scipy package are normally used far less in a given piece of Python code than those from the numpy and matplotlib packages. Therefore importing them one by one as in the above import statements is practical. This further means that once they are used, they just go under their own names with no preceding name tags. Here is an example using the norm function of the linear algebra module in the scipy package:
from scipy.linalg import norm
norm([3,4])
The function evaluates the length of the vector, and outputs 5.0.
See another example of the use of a function from scipy here.


1.2 Python as pocket calculator

Once you import the numpy package, you have access to a couple of useful constants. This cell:
import numpy as np
print(np.e)
print(np.pi)
gives the following output:
2.718281828459045
3.141592653589793
With the numpy package you further have access to all the algebraic functions you typically need when solving physics problems, e.g.:
import numpy as np
print(np.sqrt(25))
print(np.exp(1))
print(np.log(np.e))
print(np.power(3,2))
print(np.power(2,10))
print(np.cos(np.pi/2))
print(np.arccos(0) * 2)
print(np.sin(0))
print(np.arctan(1) * 180/np.pi)
that gives this output:
5.0
2.718281828459045
1.0
9
1024
6.123233995736766e-17
3.141592653589793
0.0
45.0
Notice that np.cos(np.pi/2) evaluates to 6.123233995736766e-17. This is Pythons scientific notation for the number:
which is very close to 0 (zero).
You may actually use scientific notation yourself when you write numbers:
print(np.log10(1e-17))
print(np.log10(1e4))
that gives:
-17.0
4.0
since np.log10 implements the common logarithm (the logarithm to the base 10).


1.3 Variables

Names for variables must fulfill the following:
  1. start with a letter or with _ = the underscore character
  2. contain any number of alpha-numeric characters and underscores (A-Z, a-z, 0-9, and _ )
Note that variable names are case sensitive, i.e. mass, Mass, and MASS are considered three different variables.
Note also that variable names may not start with a digit (0-9).
Choose your variable names so that they make sense and may help you recall what values they carry. Here are some great variable names:
mass = 30
velocity = [3, 4]
speed = 5
while these would generally be less good:
m = 30
v = [3, 4]
sp = 5


1.4 Variable types

There are a number of important built-in variable types in Python. You can check for the type of a variable using the type function:
mysincerity = True
mynumber = 5
myrational = 3.14
mystring = 'abc'
mylist = [2, 4, -2, 5]
mytuple = (7, 'horse')
mydict = {'yes': 25, 'no': 12}
print('type(mysincerity)',type(mysincerity))
print('type(mynumber)   ',type(mynumber))
print('type(myrational) ',type(myrational))
print('type(mystring)   ',type(mystring))
print('type(mylist)     ',type(mylist))
print('type(mytuple)    ',type(mytuple))
print('type(mydict)     ',type(mydict))
type(mysincerity) <class 'bool'>
type(mynumber)    <class 'int'>
type(myrational)  <class 'float'>
type(mystring)    <class 'str'>
type(mylist)      <class 'list'>
type(mytuple)     <class 'tuple'>
type(mydict)      <class 'dict'>
The type is best checked with the isinstance function:
print('is mynumber an int',isinstance(mynumber,int))
print('is mynumber a str ',isinstance(mynumber,str))
print('is mylist an int  ',isinstance(mylist,int))
print('is mylist a list  ',isinstance(mylist,list))
is mynumber an int True
is mynumber a str  False
is mylist an int   False
is mylist a list   True


1.5 Lists

Lists are ordered collections of Python objects. In its simplest form, a list contains values of the same type, but they may well contain dislike types of values:
asimplelist = [2, 4, -2, 5]
acomplicatedlist = [2, 'text', [100, 200]]
The elements are accessed with their indices:
print('One element:          ',asimplelist[0])
print('Another element:      ',asimplelist[1])
print('2nd lists 2nd element:',acomplicatedlist[1])
print('2nd lists 3rd element:',acomplicatedlist[2])
One element:           2
Another element:       4
2nd lists 2nd element: text
2nd lists 3rd element: [100, 200]
You may get a slice of a list, i.e. a sublist of elements from a list, by selecting with [n:m] as in:
print('Entire list: ',asimplelist)
n = 1
m = 3
print('Two elements:',asimplelist[n:m])
that selects elements from element with index n = 1 to the element right before element with index m = 3:
Entire list:  [2, 4, -2, 5]
Two elements: [4, -2]
You may leave out either n or m to get all preceding or succeeding elements:
print('Preceding elements: ',asimplelist[:m])
print('Succeeding elements:',asimplelist[n:])
print('All elements:       ',asimplelist[:])
Preceding elements:  [2, 4, -2]
Succeeding elements: [4, -2, 5]
All elements:        [2, 4, -2, 5]


1.6 Changing lists

Consider a list:
asimplelist = [10, 4, -2, 5]
asimplelist
[10, 4, -2, 5]
You can change the value of an element of the list by indexing it. Changing e.g. the first element goes like this:
asimplelist[0] = 2
asimplelist
[2, 4, -2, 5]
You can add an element to the list:
asimplelist.append(8)
asimplelist
[2, 4, -2, 5, 8]
You may remove an element, e.g. the one with index 2 by invoking the pop() method:
asimplelist.pop(2)
-2
which returns the value of the removed element and decimate the list accordingly:
asimplelist
[2, 4, 5, 8]
You may remove the last element easily:
asimplelist.pop(-1)
8
asimplelist
[2, 4, 5]
Finally, lists may be added:
new_list = asimplelist + [3, 7]
new_list
[2, 4, 5, 3, 7]


1.7 List comprehensions

Consider you have a list:
mylist = [2, 4, -2, 5]
mylist
[2, 4, -2, 5]
You can make a new list by running through your existing list and evaluate new elements one at a time. For instance, you may want to double all elements of a list:
doubledlist = [2*elem for elem in mylist]
doubledlist  
[4, 8, -4, 10]
The for and in keywords are controlling the statement together with the embracing square brackets, [ and ] that make the so-called list-comprehension appear as a list in the code even before it is evaluted. Basically, the list-comprehension runs through all elements of the list calling them elem (in this example) and evaluating what is between [ and for.
You may add an if statement and only get elements for the new list if some condition is fulfilled. Picking only elements with positive values is done like this:
positive_list = [elem for elem in mylist if elem > 0]
positive_list  
[2, 4, 5]
As final example, consider that you have a list of mixed integer and floating point values.
somelist = [3.1, 4, 4.4, 8.1, 9]
somelist
[3.1, 4, 4.4, 8.1, 9]
A list comprehension can be used to convert the list to keeping the integer elements only:
intlist = [int(el) for el in somelist if isinstance(el,int)]
intlist
[1, 5]


1.8 Tuples

Tuples are like lists ordered sequences of Python objects. The objects are separated by commas and surrounded by parentheses, ( and ). The elements of tuples are accessed like the elements of lists, but the elements of tuples cannot be changed.


1.9 Dictionaries

Dictionaries are unsorted collections of Python objects indexed by keywords. A dictionary has curly brackets, { and }, around key-value pairs that are separated by commas. The key and the value in a pair are separated by a colon, :. It may look like this:
mydict = {'dogs': 5,
          'cats': 2,
          'rats': 0}
A dictionary may be extended like this:
mydict['mice'] = 8
and queried like this:
how_many_mice = mydict['mice']
how_many_birds = mydict.get('birds',0)
where querying with the method .get(key,default) is the safe choice if one is not sure if the key-value pair exists and if one wishes to supply a default (it is optional).
You may loop over key-value pairs like this:
mydict = {'dogs': 5,'cats': 2,'rats': 0}
for key,value in mydict.items():
    print(key,value)
that gives:
dogs 5
cats 2
rats 0


1.10 Strings

Strings are sequences of characters. In this course, we shall mainly be using them as labels in plots, so we need not know a whole lot about them.
myfunctionlabel = 'f(x)'
If you need to use the single quote (the apostrophe) in your string, you may use the double quote:
myderivative = "f'(x)"


1.11 Formatted printing

Sometimes you want full control of how to print a number. E.g. a floating point value may be printed with 4 decimals in this way:
'pi: {:.4f}'.format(np.pi)
that returns a string: 'pi: 3.1416' which can be printed.
When printing in the formatted way, you insert pieces of {} in your string. For each occurence of {} an argument must be given in the .format() call. Here are some examples:
Printing two general variables:
'Arg one: {}, arg two: {}'.format(5,'five')
'Arg one: 5, arg two: five'
Specifying with {:5d} that the first argument is a integer number (with d) to be printed as 5 characters and with {:8s} that the second argument is a string (with s) to be printed on 8 characters:
'Arg one: {:5d}, arg two: {:8s}'.format(5,'five')
'Arg one:     5, arg two: five    '
Specifying with {:f}, {:.3f}, and {:.5f} that three floating point values are to be printed with the default number of decimals, with 3 decimals, and with 5 decimals, respectively:
'Arg one: {:f}, arg two: {:.3f}, arg three: {:.5f}'.format(np.pi,np.pi,np.pi)
'Arg one: 3.141593, arg two: 3.142, arg three: 3.14159'
We may also specify that 10 characters are to be used for each float as in this example:
'Arg one: {:10f}, arg two: {:10.3f}, arg three: {:10.5f}'.format(np.pi,np.pi,np.pi)
'Arg one:   3.141593, arg two:      3.142, arg three:    3.14159'
Finally, by using numbers before the colon, :, one may refer to which argument is to be inserted. Here we have only two arguments and use them in the order first, second, first, since the formatting strings, {0:10f}, {1:10.3f}, {0:10.5f}, contain the 0:, 1:, and 0: parts:
'Arg one: {0:10f}, arg two: {1:10.3f}, arg one: {0:10.5f}'.format(np.pi,2*np.pi)
'Arg one:   3.141593, arg two:      6.283, arg one:    3.14159'
See more on how format works here (use the new style).
If you wish to convert an entire list it is done like this:
mytuple = (np.pi/2,np.pi,2*np.pi)
','.join(['{:8.2f}'.format(x) for x in mytuple])
that outputs ' 1.57, 3.14, 6.28'.


1.12 Loops

If you need the same thing done a number of times, but with slightly different values, it is convenient to use a for-statement on a list (or on a more complicated Python object, an iterator, such as range):
print('--begin--')
for elem in ['zero','one','two','three']:
    print(elem)
print('--end--')
--begin--
zero
one
two
three
--end--
So the same print-statement is repeated four times, and each time the variable elem is adopting a new value from the list in the for statement. Note how the indentation (the four space-characters in front of print-statement is part of the syntax for a for-statement.
If you write more Python statements with the same indentation, all of them will be executed once for each iteration of the loop.
total_length_of_strings = 0
for elem in ['zero','one','two','three']:
    total_length_of_strings += len(elem)
    print('string: {:7s} has length: {:3d}'.format(elem,len(elem)))
print('total length of strings:    ',total_length_of_strings)
string: zero    has length:   4
string: one     has length:   3
string: two     has length:   3
string: three   has length:   5
total length of strings:     15


1.13 Lambda-functions I

Say a mathematical function, , given by:
appears a number of times in a problem for which you are writing a small Python computer code. You may then declare it as a so-called lambda-function that you give a name, for example f:
f = lambda x : x**2 - 2
The strange "lambda x" merely means that the function expects one argument. The kolon, :, and what follows defines what should be evaluated and returned whenever the function is called. Here are some examples:
print(f(0))
print(f(1),f(2))
that gives:
-2
-1 2
Learn a lot more about lambda functions here.


1.14 Lambda functions II

A function of more than one variable can also be handled in Python. Consider:
It can be written like this:
f = lambda x,sigma: 1/np.sqrt(2*np.pi)/sigma * np.exp(-x**2/2/sigma**2)
The lambda x,sigma indicates that the function expects two arguments, one for each variable. Calling a function of more than one variable, all variables must be given:
print('f(0,1)',f(0,1))
print('f(0,2)',f(0,2))
print('f(1,2)',f(1,2))
f(0,1) 0.3989422804014327
f(0,2) 0.19947114020071635
f(1,2) 0.17603266338214976
You may also call the function with lists of input data, but then you have to make sure that you only use functions, that work for lists. In the present example, x**2 and sigma**2 would not work and would have to be replaced with np.power(x,2) and np.power(sigma,2), respectively. We can then evaluate the three function values from before in one go:
import numpy as np
np.set_printoptions(precision=3)
f = lambda x,sigma: 1/np.sqrt(2*np.pi)/sigma * np.exp(-np.power(x,2)/2/np.power(sigma,2))
f([0, 0, 1],[1, 2, 2])
array([0.399, 0.199, 0.176])
A frequently occuring need is to evaluate a range of function values so that the function can be plotted. Plotting for it may look like this:
x = np.linspace(-3,3,7)
x
array([-3., -2., -1.,  0.,  1.,  2.,  3.])
f(x,1)
array([0.004, 0.054, 0.242, 0.399, 0.242, 0.054, 0.004])
f(x,2)
array([0.065, 0.121, 0.176, 0.199, 0.176, 0.121, 0.065])
f(x,3)
array([0.081, 0.106, 0.126, 0.133, 0.126, 0.106, 0.081])
fig, ax = plt.subplots()
f = lambda x,sigma: 1/np.sqrt(2*np.pi)/sigma * np.exp(-np.power(x,2)/2/np.power(sigma,2))
x = np.linspace(-np.pi,np.pi,100)
ax.plot(x,f(x,0.5),linewidth=3,color='b')
ax.plot(x,f(x,1),linewidth=3,color='r')
ax.plot(x,f(x,2),linewidth=3,color='y')
ax.grid()
ax.set_xlabel('$x$')
ax.set_ylabel('$f(x,\sigma)$')
ax.legend(['$\sigma=0.5$','$\sigma=1$','$\sigma=2$'])

Figure 2



1.15 Functions I

Built-in functions like print, type, isinstance, and so on, are in fact pieces of computer code that do well defined actions on data in variables and return results or provide some actions (e.g. generating graphical output, electronic files or the like). One may easily write new functions in Python thereby extending its capabilities while keeping the code readable. One way of doing this is to write a lambda function as described elsewhere.
The syntax of a function definition can be illustrated with this example:
def myfunc(arg1, arg2):
    print('myfunc({},{})'.format(arg1,arg2),end=' = ')
    var1 = min(10,arg1)
    var2 = min(10,arg2)
    res = var1 * var2
    return res
print(myfunc(5,7))
print(myfunc(5,12))
print(myfunc(15,12))
myfunc(5,7) = 35
myfunc(5,12) = 50
myfunc(15,12) = 100
The definition of the function starts with the def-keyword and the following variable name, here myfunc, becomes the name of the function. In parentheses, ( and ), follow the arguments, here arg1 and arg2, and then a colon, :. Every following indented statement will be a part of the function. That means the statements will be executed every time the function is called. In the example, the function is called three times. In the the first call, the statements in the function will be executed with the two variables arg1 and arg2 having values 5 and 7, respectively. In the next call of the function, the statements will be executed with arg1 and arg2 being 5 and 12, respectively, and so on.
In case you wonder what the end=' = ' means in the call of the print-function: It changes the print-function from automatically adding a line break, '\n', after the printed string(s), to adding the string following end=, in this case ' = '. Here is another example:
print('123')
print('456',end='...')
print('789')
123
456...789


1.16 Functions II

A function can be defined with default values for the arguments. Here is a an example for a function with three arguments:
def mysum(x=5,y=7,z=11):
    res = x + y + z
    print('x={} y={} z={} res={}'.format(x,y,z,res))
    return x + y + z
Calling the function with all three arguments gives the expected result:
mysum(1,2,3)
x=1 y=2 z=3 res=6
But leaving out values for some of the arguments now also works, thanks to the declaration of default values in the function declaration:
mysum(1,2)
mysum(1)
mysum()
x=1 y=2 z=11 res=14
x=1 y=7 z=11 res=19
x=5 y=7 z=11 res=23
When values for arguments are given for function as done in the example, the arguments are called positional arguments. However, with defaults set for function arguments, the function may be called with so-called keyword arguments, where it is specified explicitly what arguments are assigned which values. For instance, the z argument may given like this without any positional arguments, or with for example the first positional argument given:
mysum(z=0)
mysum(1,z=0)
x=5 y=7 z=0 res=12
x=1 y=7 z=0 res=8
Keyword arguments may even be given in another order than if they were given as positional arguments.
mysum(z=0,y=2)
x=5 y=2 z=0 res=7
Note, however, that once you have started giving keyword arguments, you cannot give any more positional arguments. I.e. mysum(1,z=0,3) would not work, but throw the error message: SyntaxError: positional argument follows keyword argument.


1.17 Boolean

A variable of the Boolean type may only take two values, either True or False. Variables of other types may be converted to Boolean type, e.g. integers:
bool(-1), bool(0), bool(1), bool(2)
(True, False, True, True)
or strings:
bool(''), bool('0'), bool('1'), bool('False'), bool('True') 
(False, True, True, True, True)
A special case is the NoneType value, None, that evaluates to False:
bool(None)
False
Finally, empty tuples, lists, or dictionaries, all evaluate to False:
bool(()), bool([]), bool({})
(False, False, False)
While tuples, lists, or dictionaries with some content evaluate to True.
Thus in practise, the Boolean representation of a value is True except if they are an integer 0, an empty string, '', the NoneType value, None, or an empty tuple, list, or dictionary, (), [], or {}, in which case their Boolean representation is False.


1.18 Boolean expressions

A number of operators evaluate to values of the Boolean type. An example would be the == operator that requires its two arguments to evaluate to the same value in order to return True:
0 == 0, 0 == 5 - 5, 'three' == 'Three'.lower()
(True, True, True)
returning False otherwise:
0 == 1, 3 == 3 - 6, 3 == 'three'
(False, False, False)
There are a number of other boolean comparison operators. Examples are >, <, <=, etc.
A most useful boolean membership operator is in that tests if a value appears in a sequence (a string, a tuple, a list, a dictionary):
'a' in 'char', 3 in (1, 2), 3 in [2, 3], 3 in {2: 'two', 3: 'three'}
(True, False, True, True)
Boolean expression may be combined with and and or:
expr1 = 1 == 1 and 1 > 2
expr2 = 1 == 1 or 1 > 2
expr1, expr2
(False, True)
and negated with not:
not True, not(True), not(False), not(1==2), 1 not in [0, 2, 4]
(False, False, True, True, True)
that is seen to work both as an operator (e.g. not True) and as a function (e.g. not(True)).


1.19 Branching

Often, when some Python code is to do different actions depending on the actual value of data, the if-else compound statement is invoked. In one of its simplest forms it may look like this:
myinput = input('Write something and hit ENTER: ')
if myinput:
   print('myinput as Boolean is True')
else:
   print('myinput as Boolean is False')
The myinput appearing after if is treated as an expression that is evaluted and converted to Boolean type. If the result is True any indented statements following the colon, :, are executed, otherwise, the indented statements following the else: are executed.
It is possible to test for several conditions in sequence using the keyword elif and constructing a if-elif-else compound statement as in this example:
yourstring = input('Write a number')
if yourstring == '0':
    res = 'zero'
elif yourstring.isdigit():
    res = 'positive'
elif yourstring[0] == '-' and yourstring[1:].isdigit():
    res = 'negative'
else:
    res = 'not a number'
print('Your input {} is {}'.format(yourstring,res))


Sci2u Assignment: 820
Delete "Python book"?
Once deleted this booklet is gone forever!
Block is found in multiple booklets!

Choose which booklet to go to:

© 2019-2022 Uniblender ApS