Python Tutorial


In [ ]:
from __future__ import print_function

Hello World!


In [ ]:
# Output "Hello World!"
print("Hello, World!")
print("Hello World!", 10.0)
  • # starts a comment line.
  • f(x,y) is a function call. f is the function name, x and y are the arguments.

Values, Types, Variables


In [3]:
# define a variable
s = "Hello World!"
x = 10.0
i = 42

# define 2 variables at once
a,b = 1,1

In [4]:
# output the types
print(type(10.0), type(42), type("Hello World!"))
print(type(s), type(x))


<class 'float'> <class 'int'> <class 'str'>
<class 'str'> <class 'float'>

In [5]:
# now change the type of s!
s = 3
print(type(s))


<class 'int'>
  • RHS of = (10.0, "Hello World") are values.
  • LHS of = (s, x, ...) are variables.
  • Values have a type.
  • We can assign more than one variable in a single assignment.
  • type(x) can be used to determine the type of x.
  • variables can change their type.

Strings


In [1]:
name = "olaf"
print(len(name))
print(name.capitalize())
print(name.upper())
print(name[2])


4
Olaf
OLAF
a
  • Python has strings.
  • Various functions to modify strings.
  • These functions return the new value.
  • The strings itself are immutable!

Ints and Floats


In [ ]:
x = 2.0
i = 42
print(type(x), type(i))

In [ ]:
# math expressions
y = (-2*x**3 + x**.5) / (x-1.0)
n = (-2*i**3 + 23)
print(y)
print(n)

In [ ]:
# mixed expressions
y = (i*x + x**2)
print(y)

In [ ]:
# division!
print("17 / 2 =", 17/2)
print("17. / 2 =", 17./2)
print("17 % 2 =", 17%2)
print(float(i)/2)
print((i+0.)/2)

In [ ]:
# unary operators
i += 10
i -= 7
x /= 3.0
print(i, x)

In [ ]:
print(3 * 10)
print("3" * 10)
  • "Standard" math operators exist: +, -, *, /, **
  • Be careful with /: integer division when both numbers are integers! (only Python 2!)
  • Unary operators +=, -=, ...
  • Operators may behave differently depending on the type.

Boolean Expressions


In [ ]:
truth = True
lie = False
print(type(truth))
print(truth)
print(not lie and (truth or lie))

In [ ]:
truth = (i == 42)
truth = lie or (i == n) and (x != y) or (x < y)
  • Boolean values are True and False.
  • and, or and not are logical operators.
  • ==, !=, <, >, <=, >= are comparison operators.

Formatted Output


In [ ]:
print("x={}, y={}".format(x, y))

In [ ]:
print("y={1}, x={0}".format(x, y))

In [ ]:
x = 3.14159
print("x={:.4}, x={:5.3}".format(x, y))
  • str.format() to format output (was "%")
  • {} is replaced by function arguments in order
  • {1} explicitely denotes the second argument
  • {:5.3} can be used to format the output in more detail (here: precision)

Lists


In [6]:
# create an empty list
l = []

# append different elements
l.append("Hallo")
l.append("Welt!")
l.append(42)
l.append(23)
l.append([1.0, 2.0])

# create a number range
ns = range(20)

# output the list
print(l)
print(ns)
print(range(7,15))


['Hallo', 'Welt!', 42, 23, [1.0, 2.0]]
range(0, 20)
range(7, 15)

In [ ]:
print(len(ns))

In [ ]:
# access elements
print(l[0])
print(l[2])
print(l[-1])

In [ ]:
# take slices
print(ns)
print(ns[2:7])
print(ns[17:])
print(ns[:7])
# with stride
print(ns[7:16:2])

In [ ]:
# unpack the list
print(l)
s1, s2, n1, n2, _ = l
print(s1, s2)

In [ ]:
print(17 in ns)
print("Hallo" in l)
  • Python provides lists.
  • [] is an emtpy list.
  • list.append(value) can be used to append anything to a list.
  • Nested lists are possible.
  • range(start, end) creates a list of numbers
  • len(list) returns the length of the list.
  • list[i] to access the ith element of the list (start counting with 0).
  • Negative indices denote elements from the end.
  • Slices can be used to take sublists.
  • A list can be unpacked in an assignment.
  • _ can be used to ignore an element.
  • in to find an element in a list.

Control Structures


In [ ]:
fib = []
a, b = 0, 1

while b < 100:
    a, b = b, (a+b)
    fib.append(a)

print(fib)

In [ ]:
for n in fib:
    if n % 3 == 0:
        print("{} is modulo 3!".format(n))
    elif n % 2 == 0:
        print("{} is even".format(n))
    else:
        print("{} is odd".format(n))
  • while, if, else, for control structures
  • Indentation is significant! All lines with the same indent belong to one block
  • : at end of previous line starts a new block
  • while is a loop with an end condition
  • for is a loop over elements of a list (or other generators)

Function Definitions


In [ ]:
# define a function
def f(x, c):
    return x**2-c, x**2+c

print(f(3.0, 1.0))
print(f(5.0, 2.0))

In [ ]:
# with default argument
def f(x, c=1.0):
    return x**2-c, x**2+c

print(f(3.0))
print(f(5.0, 2.0))

In [ ]:
# with docstring
def f(x):
    "Computes the square of x."
    return x**2

In [ ]:
help(f)
  • def to define a function
  • return defines the return values of the function
  • * to unpack lists/take argument lists

Variable Scoping


In [ ]:
def f(x):
    print("i =", i)
    print("x =", x, "(in function, before add)")
    x += 2
    print("x =", x, "(in function, after add)")
    return x

x = 3
i = 42
print("x =", x, "(in script, before call)")
y = f(x)
print("x =", x, "(in script, after function call)")
print("y =", y)

In [ ]:
x = 3

def f():
    global x
    x += 2

print("x =", x, "(before call)")
f()
print("x =", x, "(after function call)")
  • Local variables override global variables.
  • Global variables are not modified when changing local variables.
  • Still, in a function definition, global variables can be accessed (i.e., they are copied).
  • When the global variable should be modified inside a function, explicitely declare it with global.

Variables contain References


In [ ]:
l = ["Hello", "World"]
ll = [l, l]
print(ll)

l[1] = "Olaf"
print(ll)

ll[0][1] = "Axel"
print(ll)
  • Variables are references to values.
  • When an value is modified, all variables that reference it get changed.
  • Basic types are immutable, i.e. they cannot be modiified.
  • When they are assigned to another variable, a new copy is created.
  • Functions modifying them return a new, modified version.
  • Not so with other types!

Classes and Objects

  • Classical Python programs contain variables that have a value of a certain data type, and functions.
  • Observation: functions are tied to a given data type.
  • For example, print should behave differently when used with a string, and integer, or a file. The same basically holds for all functions.
  • Idea: Tie functions to the data type also syntactically
    • The world is made of objects (a.k.a. value)
    • An object is an instance of a class (a.k.a. data type)
    • A class provides methods (a.k.a. as functions) that can be used to do anything with these objects.

In [ ]:
# Create an object of class "file"
f = file('test.txt', 'w')
# Call the method "write" on the object
f.write('Hello')
# Close he file
f.close()
  • file is a class.
  • When using a class like a function, this will create an object (a.k.a. an instance of a class): f = file('test.txt', 'w')
  • Several instances/objects of a class can be created.
  • An object has methods (a.k.a. class functions) that can be used to do something with the object.
  • Methods are called like object.method(): f.write('Hello')

Everything is an object


In [ ]:
s = "Hello {}"
print(s.format("World!"))
print("Hello {}".format("World"))

x = 42.0
print(x.is_integer())
print((42.0).is_integer())

# same as l=[]
l = list()
l.append(42)
l.append(23)
  • All types in Python are classes, all values are objects!

Defining a Class


In [ ]:
class Circle:
    "This class represents a circle."
    
    def create(self, r):
        "Generate a circle."
        self.radius = r          

    def area(self):
        "Compute the area of the circle."
        return 3.14159 * self.radius**2
    
help(Circle)

In [ ]:
# create two circles
c1 = Circle()
c1.create(2.0)
c2 = Circle()
c2.create(3.0)

print(c1.area())
print(c2.area())
print(c2.radius)
  • Create a class using the keyword class.
  • Methods are nested functions.
  • A method gets the object itself as first argument (usually called self).
  • Methods can access and modify fields (a.k.a. instance variables).

Special Methods


In [ ]:
class Circle:
    pi = 3.14159
    
    # __init__ is the constructor
    def __init__(self, r):
        self.radius = r

    def area(self):
        return Circle.pi * self.radius**2
        
    # define operator "+"
    def __add__(self, other):
        new = Circle(((self.area() + other.area())/3.14159)**0.5)
        return new
    
    # define how to convert it to a string (e.g. to print it)
    def __str__(self):
        return "I am a circle with radius {}.".format(self.radius)
    
c1 = Circle(2.0)
c2 = Circle(3.0)
print(c1.area())
print(c2.radius)

# We have defined "__add__", so we can add two circles
c3 = c1 + c2
print(c3.radius)
print(c3.area())

# We have defined "__str__", so we can print a circle
print(c1)
  • __init__ is the constructor.
  • Other special functions can be used to allow operators etc.

In [ ]:
# same a + 23
a = 19
print(a.__add__(23))
# same as "Hello Olaf!"[6:10]
print("Hello Olaf!".__getslice__(6, 10))
  • Ultimately, the language intrinsics of Python are
    • assignments
    • function definitions
    • class definitions
    • method or functions calls
  • The rest (e.g. all operators) are "syntactical sugar" and use special methods (e.g. __add__).

In [ ]:
class Polynomial:
    "Represents a polynomial p(x)=a*x**2 + b*x + c."
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    # allows the object to be used as a function
    def __call__(self, x):
        return self.a*x**2 + self.b*x + self.c
    
p = Polynomial(3.0, 2.0, 1.0)

print(p(1.0))

Inheritance


In [ ]:
class MyCircle(Circle):
    def __init__(self, r = 1.0, color = "red"):
        Circle.__init__(self, r)
        self.color = color
    def __str__(self):
        return "I am a {} circle with radius {} and area {}.".format(self.color, self.radius, self.area())
    
c1 = MyCircle()
c2 = MyCircle(2.0, "green")
print(c1)
print(c2)
print(c1 + c2)
  • A class can inherit all methods from another class.
  • The inherited methods can be overridden.
  • Allows to extend functionality of a class.

Modules


In [ ]:
import math
print(math.pi)
print(math.sin(math.pi))

import sys
print("Hello World!", file=sys.stderr)

In [ ]:
from math import sin, pi
print(sin(pi))

In [ ]:
from math import *
print(log(pi))
  • import makes functions, variables and classes from a module available.
  • Functions in a module need to be qualified to call them.
  • This is like calling a method. Wait, it is calling a method!
  • from, import draws the members of the module into the global namespace.