Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
24 views195 pages

All Class PPT in One

The document provides an introduction to programming concepts using Python, covering topics such as variables, data types, operations, functions, and debugging. It includes examples of code snippets and exercises to reinforce learning. The content is based on 'Think Python 2nd Edition' by Allen B. Downey.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views195 pages

All Class PPT in One

The document provides an introduction to programming concepts using Python, covering topics such as variables, data types, operations, functions, and debugging. It includes examples of code snippets and exercises to reinforce learning. The content is based on 'Think Python 2nd Edition' by Allen B. Downey.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 195

Introduction to Programming

Intro

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Hello World

# yay, hello world


print('hello world')

1
Values, Variables, Assignments

• We can assign values to variables


• We can choose names, subject to some rules
• Rules:
https://greenteapress.com/thinkpython2/html/thinkpython2003.html#sec17

speed_limit = 50
robot_name = 'bob the rob'
my_height = 1.95

2
Print

• We can print values to the console

print(50)
print(robot_name)

3
Types

• Values have types


• e.g. integer: whole numbers, float: real numbers, string: text
• We will get to know more types

type(50) # int
type(1.1) # float
type(robot_name) # str

4
Operations on Numbers

• We can perform operations on values and variables (that have a value)


• Try those with integers, floats and mix them. What’s the type of resulting values?
• Try to divide by zero. What happens?

1 + 1 # addition
1 - 1 # subtraction
1 * 1 # multiplication
my_height / 2 # division
4 // 3 # division without remainder
4 % 3 # modulus
1 ** 2 # exponentiation

5
Operations on Strings

• Try to divide strings. What happens?


• Also try other operations. What happens?

'bob' + ' the rob' # string concatenation


robot_name + ' rocks!' # 'bob the rob rocks!'
'bob' * 2 # 'bobbob'

6
A Note on Quotation Marks

• Both single and double quotes mark a string


• You can use the other type for printing quotes

print('bob is a "robot"')
print("a 'robot' is bob")

7
Operator Precedence

• Operations are applied wrt. their precedence


• PEMDAS: Parentheses, exponentiation, multiplication, division, addition,
subtraction
• Try to come up with expressions and predict their value. Then check by executing
and printing the expressions in python.

x = 1 + 2 * 3
x = (1 + 2) * 3
x = 1+2 * 3 # whitespaces don't affect precedence

8
Expressions and Statements

• Expressions evaluate to a value and can be assigned to variables


• Statements are execution instructions and have no value
• Try to print a compound expression, e.g. print(1 + 1). What happens?
• Try to print a statement, e.g. print(x = 42). What happens?
• Try x = y = 1. What does that mean? What about x = (y = 1)?
• Is print(42) a statement or an expression?

1 + 2 # expression, value is 3
x = 1 + 2 # statement (assignment), no value

9
Debugging

• Debugging allows to execute a program step by step


• Modern IDEs show the change of variables’ values due to each program step
• This may be very helpful when learning to program
• Write a small program and debug it
• Make this a habit :)

10
Introduction to Programming
Functions

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Function Calls

• A function is a named sequence of statements


• A function call looks like function_name(arguments)
• Functions (may) take arguments and return values

type(42)
print('hello')

1
Type Conversion

• There are built-in functions for converting types of values

int('42')
int(-3.9)
float('4.2')
float(42)
str(42)

2
Math Functions, Modules

• Python has a math module containing mathematical operations


• https://docs.python.org/3/library/math.html
• We can import a module with an import statement
• There are many more modules to be imported :)

import math

x = math.sin(0)
y = math.sqrt(2)
print(math.pi)

3
Composition

• We can compose expressions and statements


• We can assign compound expressions to variables
• We can use compound expressions as function arguments
• We can use function calls as function arguments

x = math.sin(3 * math.pi)
y = math.exp(math.log(x + 1))

4
Defining Functions

• We can define our own functions


• The first line is the header
• The empty parentheses say that this function does not take arguments
• The following indented lines are the body

def make_some_sound():
print('da')
print('du')

5
Why Functions?

• Readability
• Maintainability
• Reusability
• Testability

6
Functions are Objects

• Functions are objects and have a type


• We’ll learn later what an object exactly is
• Btw. modules are objects too :)
• Look at this with a debugger

print(make_some_sound)
type(make_some_sound)
import math
print(math)

7
Call Your Function

• We call our own functions the same way as built-in functions


• Try to call it with an argument. What happens?

make_some_sound()
make_some_sound('huh')

8
Functions in Functions

• We can call functions inside another function


• What would you expect when calling make_a_lot_of_sound()?

def make_a_lot_of_sound():
make_some_sound()
make_some_sound()

9
Definition and Use

• Function definitions get executed like other statements


• Executing a function definition creates a function object
• Statements inside the function do not run until the function is called
def make_some_sound():
print('da')
print('du')

def make_a_lot_of_sound():
make_some_sound()
make_some_sound()

make_a_lot_of_sound()
10
Flow of Execution

• Try to change the order of definitions and calls. What happens?


• Can you write the same program without a function definition?
• Use the debugger to see what’s going on

11
Parameters and Arguments

• We can define functions that take arguments


• Inside the function, the arguments are assigned to variables we call parameters

def make_sound_twice(sound):
print(sound)
print(sound)

make_sound_twice('deh')
sound = 'doo'
make_sound_twice(sound)
make_sound_twice(42 + math.pi)

12
Keyword Arguments

• We can pass arguments with their name explicitly, which may increase
comprehensibility
• These are called keyword arguments
• We can mix arguments without and with keywords, keyword arguments have to be
passed after those without

def power(base, exponent):


print(base ** exponent)

f(1, 2)
f(1, exponent=2)
f(base=1, exponent=2)

13
Scope

• Variables and parameters in a function are local


• Variables defined inside a function are destroyed when the function terminates
• Use the debugger and its ’step into’ functionality :)
• What happens if you assign a = 1, b = 2 and call add(a, b)?

def add(a, b):


a_plus_b = a + b
print(a_plus_b)

add(1, 2)
print(a_plus_b) # NameError: name 'a_plus_b' is not defined

14
Return Values

• Some function return values, e.g. math.cos(math.pi)


• Others return a special value None

x = math.cos(math.pi)
y = print('robbedibobby')
print(type(y))
z = make_sound_twice(y) # huh

15
Stack Diagrams

• Stack diagrams are useful to understand variables and scope


• Each function call is represented by a frame
• Note the effect of function definition (creates an object) and call (creates a frame)
• We can access variables from the global frame in the other frames
• We can’t access variables from other frames other than the global frame
• http://pythontutor.com/

16
Turtle

• Our next built-in module: turtle


• We can create images with turtle

import turtle
donatello = turtle.Turtle()
print(donatello)
turtle.mainloop()

17
Turtle Methods

• We can move our turtle with methods


• A method is like a function belonging to an object
• We’ll learn more about methods later
• We can call a method with dot notation
• There are many methods for turtle:
https://docs.python.org/3/library/turtle.html

donatello = turtle.Turtle()
donatello.forward(42) # or backward(24)
donatello.right(10) # or left(11)
donatello.penup() # or pendown()
turtle.mainloop()

18
Repetition

• You can repeat things with a for loop


• We’ll learn more about repetition later
• We can use this to draw a square

for i in range(4):
print('shoobidoo')

for i in range(4):
donatello.forward(100)
donatello.left(90)

19
Introduction to Programming
Functions - Exercises

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Exercises

• Try to change the order of definitions and calls. What happens?


• Can you write the same program without a function definition?
• Use the debugger or python tutor to see what’s going on

def make_some_sound():
print('da')
print('du')

def make_a_lot_of_sound():
make_some_sound()
make_some_sound()

make_a_lot_of_sound()

1
Exercises

• What do the following programs output? Why?


• Follow the program flow in python tutor, and try to predict what will happen at every step.

# program 1
def f(x):
y = x + 1
print(y)
f(1)

# program 2
def f(x):
y = x + 1
print(y)
f(1)

2
Exercises

• What does the following program output?


• Follow the program flow in python tutor, and try to predict what will happen at every step.

def f(x):
y = x + 1
print(y)
y = 1
f(y)
print(y)

3
Exercises (cf. Think Python, Section 4.3)

• Write a function called square that takes a parameter named t, which is a turtle object. The
function should use the turtle to draw a square. Create a turtle object, and call square with that
turtle object as an argument.
• Add another parameter, named length, to square. Modify the body such that the length of the
sides is length, and then modify the function call to provide a second argument. Test your
program with a range of values for length.
• Make a copy of square and change the name to polygon. Add another parameter named n and
modify the body so it draws an n-sided regular polygon. Hint: The exterior angles of an n-sided
regular polygon are 360/n degrees.
• Write a function called circle that takes a turtle and a radius as parameters. The function should
draw an approximate circle by calling polygon with an appropriate length and number of sides.
Test your function with a range of values for the radius parameter. Hint: figure out the
circumference of the circle and make sure that length * n = circumference.
• Make a more general version of circle called arc that takes an additional parameter angle, which
determines what fraction of a circle to draw. angle is in units of degrees, so when angle=360, arc
should draw a complete circle. 4
Introduction to Programming
Functions - Exercises

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Exercises

• Try to change the order of definitions and calls. What happens?


• Can you write the same program without a function definition?
• Use the debugger or python tutor to see what’s going on

def make_some_sound():
print('da')
print('du')

def make_a_lot_of_sound():
make_some_sound()
make_some_sound()

make_a_lot_of_sound()

1
Solution

• Calling a function before defining it yields an error

def make_some_sound():
print('da')
print('du')

make_a_lot_of_sound()

def make_a_lot_of_sound():
make_some_sound()
make_some_sound()

2
Solution

• Calling a function when defining another function’s body can happen before the actual definition,
as the code inside the function’s body is not executed until it is actually called

def make_a_lot_of_sound():
make_some_sound()
make_some_sound()

def make_some_sound():
print('da')
print('du')

make_a_lot_of_sound()

3
Solution

• We can achieve the same effect without using functions


• But: No reusable function definition

print('da')
print('du')
print('da')
print('du')

4
Exercises

• What do the following programs output? Why?


• Follow the program flow in python tutor, and try to predict what will happen at every step.

# program 1
def f(x):
y = x + 1
print(y)
f(1)

# program 2
def f(x):
y = x + 1
print(y)
f(1)

5
Solution

• Program 1 outputs 2
• y is a local variable, getting assigned the value 1 + 1, which is 2

# program 1
def f(x):
y = x + 1
print(y)
f(1)

6
Solution

• Program 2 outputs a NameError


• y is undefined in the global frame when calling print(y)

# program 2
def f(x):
y = x + 1
print(y)
f(1)

7
Exercises

• What does the following program output?


• Follow the program flow in python tutor, and try to predict what will happen at every step.

def f(x):
y = x + 1
print(y)
y = 1
f(y)
print(y)

8
Solution

• This program prints 1 followed by 2


• The global variable y and the local variable y are two different objects

def f(x):
y = x + 1
print(y)
y = 1
f(y)
print(y)

9
Exercises (cf. Think Python, Section 4.3)

• Write a function called square that takes a parameter named t, which is a turtle object. The
function should use the turtle to draw a square. Create a turtle object, and call square with that
turtle object as an argument.
• Add another parameter, named length, to square. Modify the body such that the length of the
sides is length, and then modify the function call to provide a second argument. Test your
program with a range of values for length.
• Make a copy of square and change the name to polygon. Add another parameter named n and
modify the body so it draws an n-sided regular polygon. Hint: The exterior angles of an n-sided
regular polygon are 360/n degrees.
• Write a function called circle that takes a turtle and a radius as parameters. The function should
draw an approximate circle by calling polygon with an appropriate length and number of sides.
Test your function with a range of values for the radius parameter. Hint: figure out the
circumference of the circle and make sure that length * n = circumference.
• Make a more general version of circle called arc that takes an additional parameter angle, which
determines what fraction of a circle to draw. angle is in units of degrees, so when angle=360, arc
should draw a complete circle. 10
Encapsulation

• Placing code that does a certain thing in a function is called encapsulation


• Naming may aid readability and comprehensibility
• Allows to reuse code

def square(t):
for i in range(4):
t.forward(100)
t.left(90)

square(donatello)
leonardo = turtle.Turtle()
square(leonardo)

11
Generalization

• Adding a parameter to a function is called generalization


• It makes the function more general

def square(t, length):


for i in range(4):
t.fd(length)
t.lt(90)

square(bob, 100)

12
Generalization

• Generalizing square to polygon

def polygon(t, n, length):


angle = 360 / n
for i in range(n):
t.fd(length)
t.lt(angle)

polygon(bob, 7, 70)

13
Keyword Arguments

• We can assign names to arguments


• These are called keyword arguments
• They help to keep track of which argument means what

polygon(bob, n=7, length=70)

14
Interface Design

• The interface of a function is a summary of how it is used


• What are the parameters?
• What is the return value?
• This allows to hide details from users of the function

import math

def circle(t, r):


circumference = 2 * math.pi * r
n = 50
length = circumference / n
polygon(t, n, length)

15
Interface Design

• There is no ’correct’ interface, it is always a decision


• We could make n a parameter of the function
• Or we can adapt it wrt. circumference, hiding rendering details from the caller

def circle(t, r):


circumference = 2 * math.pi * r
n = int(circumference / 3) + 3
length = circumference / n
polygon(t, n, length)

16
Refactoring

• We were able to reuse polygon when implementing circle


• It’s different with arc
• We can’t reuse polygon without changing its interface
def arc(t, r, angle):
arc_length = 2 * math.pi * r * angle / 360
n = int(arc_length / 3) + 1
step_length = arc_length / n
step_angle = angle / n

for i in range(n):
t.fd(step_length)
t.lt(step_angle)
17
Refactoring

• We can generalize polygon with the angle between segments


• It’s not necessarily a polygon anymore, so let’s rename it

def polyline(t, n, length, angle):


for i in range(n):
t.fd(length)
t.lt(angle)

18
Refactoring

• We now can use polyline for polygon, arc, and refactor circle

def polygon(t, n, length):


angle = 360.0 / n
polyline(t, n, length, angle)

def arc(t, r, angle):


arc_length = 2 * math.pi * r * angle / 360
n = int(arc_length / 3) + 1
step_length = arc_length / n
step_angle = float(angle) / n
polyline(t, n, step_length, step_angle)

def circle(t, r):


arc(t, r, 360)
19
Docstring

• A docstring is a string at the beginning of a function that explains the interface

def polyline(t, n, length, angle):


"""Draws n line segments with the given length and
angle (in degrees) between them. t is a turtle.
"""
for i in range(n):
t.fd(length)
t.lt(angle)

20
Introduction to Programming
Conditions, Recursion and Return Values

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Recap

• Variables, Values, Types, Operations


• Functions, Scope

1
Boolean Expressions

• Evaluate to True or False


• Are of type bool
• Try those with numerical types, strings and booleans

x == y # x is equal to y
x != y # x is not equal to y
x > y # x is greater than y
x < y # x is less than y
x >= y # x is greater than or equal to y
x <= y # x is less than or equal to y

2
Logical Operators

a and b
n % 2 == 0 or n % 3 == 0
not x > 0

3
Conditional Execution

• Conditional statements allow for conditional execution


• if statements have the same structure as function definitions: a header followed by
an indented body
• The boolean expression after if is called the condition

if x > 0:
print('x is positive')

4
Conditional Execution

• if-else statements allow for alternative execution


• Alternatives are called branches

if x % 2 == 0:
print('x is even')
else:
print('x is odd')

if x % 2 == 0:
print('x is even')
if not x % 2 == 0:
print('x is odd')

5
Chained Conditional Execution

• elif abbreviates else if


• Exercise: Write equivalent code using if and not (without using elif and else)

if x < y:
print('x is less than y')
elif x > y:
print('x is greater than y')
else:
print('x and y are equal')

6
Chained Conditional Execution

• Conditions are checked in order


• Only one branch is executed

if choice == 'a':
draw_a()
elif choice == 'b':
draw_b()
elif choice == 'c':
draw_c()

7
Nested Conditionals

• Branches contain python programs


• So they can also contain conditional statements
• Too deep nesting may be a sign for refactoring potential

if x == y:
print('x and y are equal')
else:
if x < y:
print('x is less than y')
else:
print('x is greater than y')

8
Return Values

• Functions return values

e = math.exp(1.0)
height = radius * math.sin(radians)

def area(radius):
a = math.pi * radius ** 2
return a

def absolute_value(x):
if x < 0:
return -x
else:
return x

9
Return Values

• What value does print('hi') return?


• Branches without an explicit return statement return None

def absolute_value(x):
if x < 0:
return -x
if x > 0:
return x

print(absolute_value(0))

10
Boolean Return Values

• We can use boolean return values to give logical tests readable names

def is_divisible(x, y):


return x % y == 0

if is_divisible(4, 2):
print('divisible')

11
Type Checking

• We can check the type of a variable with the built-in boolean function
isinstance(value, type)

x = 'hi'

if isinstance(x, str):
print('str')
if isinstance(x, int):
print('int')
if isinstance(x, float):
print('float')
if isinstance(x, bool):
print('bool')

12
Recursion

• A function can call itself


• This is called recursion
• Highly recommended: Look at recursion with http://pythontutor.com/

def countdown(n):
if n <= 0:
print('Blastoff!')
else:
print(n)
countdown(n-1)

13
Infinite Recursion

• To terminate, a recursive function needs a non-recursive base case


• What happens here?

def recurse():
recurse()

14
Recursive Sum

• Define a function sum(n) returning 1 + 2 + ... + n


• Base case: Note that sum(1) equals 1
• Induction: Note that sum(n) equals 1 + 2 + ... + n, which equals sum(n - 1) + n
• What happens if you call sum(0)?

def sum(n):
# base case
if n == 1:
return 1
# inductive case
else:
return n + sum(n - 1)
15
Random

• Another built-in module: random, it generates random numbers


• https://docs.python.org/3/library/random.html
import turtle
import random

def move(t, n):


distance = random.randint(10, 100)
t.forward(distance)
angle = random.randint(-90, 90)
t.right(angle)
move(t, n - 1)

donatello = turtle.Turtle()
move(donatello, 100)
turtle.mainloop()
16
Introduction to Programming
Conditions, Recursion and Return Values - Exercises

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Exercises

• Write a compare function that takes two values, x and y, and returns 1 if x > y, 0
if x == y, and -1 if x < y.
• Write a function is between(x, y, z) that returns True if x ≤ y ≤ z or False
otherwise.
• Write a function that takes two points given by their coordinates x0, x1 and y0,
y1 as arguments, and returns the euclidean distance between them.

1
Exercises

• Write a recursive function factorial(n) that takes n as an argument, and


returns the factorial n!. Note that 0! = 1 (base case) and n! = n · (n - 1)!.
• Look at your factorial function for some n (e.g. n = 2) using a debugger and/or
http://pythontutor.com/. Explain what’s going on. Particularly note the local
frames and variable assignments.
• What happens if you call factorial(1.5)?
• Use isinstance to ensure the argument is an integer. Print some message
otherwise, indicating that the caller should provide an integer as argument.
• Write a recursive function fibonacci(n) for computing the fibonacci number for n.
See https://en.wikipedia.org/wiki/Fibonacci_number

2
Generative Processes

• Can you combine random numbers, conditions, recursion and turtle’s methods to
create generative art? See next slide for some ideas.
• https://docs.python.org/3/library/turtle.html

t = turtle.Turtle()
t.penup()
t.pendown()
t.pensize(size)
t.pencolor(r, g, b)
t.fillcolor(r, g, b)
t.begin_fill()
t.end_fill()

3
Generative Processes

• Draw multiple squares with various/random position, rotation and color


• Draw noisy shapes by randomizing side length and/or angle
• Randomly draw different shapes, e.g. triangles, squares or circles
• Try to keep turtle inside the window if it wants to leave it. Hint: use
turtle.position() to get turtle’s position, and turtle.screensize() to get the window
size. Note that the origin (i.e. position (0, 0)) of turtle’s coordinate system is in
the center of the window.

4
Exercises

• For more exercises, see https:


//greenteapress.com/thinkpython2/html/thinkpython2007.html#sec80

5
Introduction to Programming
Iteration

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Overview

• Structure of programs
• Variables, Values, Types, Operations
• Functions, Scope
• Conditions, Return Values
• Recursion, Iteration
• Structure of data (starting next week)

1
While Loop

1. Determine whether the condition is true or false


2. If false, exit the while statement and continue execution at the next statement
3. If the condition is true, run the body and then go back to step 1

def countdown(n):
while n > 0:
print(n)
n = n - 1
print('Blastoff!')

2
Break

• We can use the break statement to ’leave’ the loop at any time
• input(prompt) queries input from the user showing the prompt in the terminal,
and returns the string entered by the user

while True:
line = input('> ')
if line == 'done':
break
print(line)

print('Done!')

3
Not exactly the same as break

• This would print ’done’ before ’Done!’

line = ''
while line != 'done':
line = input('> ')
print(line)

print('Done!')

4
Factorial with While

• In contrast to recursion

def factorial(n):
fac = 1
while n > 0:
fac = fac * n
n = n - 1
return fac

5
Infinite While

• To stop an infinitely running program, hit ’ctrl + c’

while True:
print('still on')

6
Random Walk

• Simulation with randomness

import turtle
import random

t = turtle.Turtle()
steps = 100
while steps >= 0:
t.forward(random.randint(10, 50))
t.left(random.randint(-180, 180))
steps = steps - 1
turtle.mainloop()

7
Simulation

# initialize state
x = 0
y = 0
v_x = 0
v_y = 0
simulate = True
while simulate:
# sense some information
print(x, y)
# change or set our activation (e.g. velocity)
v_x = random.randint(0, 10)
v_y = random.randint(0, 10)
print('vehicle chose velocity: ' + str(v_x) + ', ' + str(v_y))
# update the state of the simulation
x = x + v_x
y = y + v_y
# until we don't want to simulate anymore
if x > 20:
simulate = False
8
Packages with pip

• We can install python packages with pip: In a terminal, write ’pip install
<packagename>’
• For example termcolor for printing colored strings: ’pip install termcolor’
• https://pypi.org/project/termcolor/
• We can import particular definitions from a module using from ... import ...

from termcolor import colored

name = input('what is your name? ')


message = 'hello ' + colored(name, 'magenta')
print(message)

9
Implementing a Fibonacci Sequence
In this assignment, you will explore different methods to calculate the Fibonacci sequence, a
series of numbers where each number is the sum of the two preceding ones, usually starting
with 0 and 1. Your task is to implement the Fibonacci sequence using three different approaches
in Python:

1. While Loop Implementation:

Write a function fibonacci_while(n) that takes an integer n and returns the first n
numbers of the Fibonacci sequence using a while loop.

2. For Loop Implementation:

Write a function fibonacci_for(n) that achieves the same goal as above, but by using
a for loop.

3. Recursive Implementation:

Write a function fibonacci_recursive(n) that calculates the first n numbers of the


Fibonacci sequence using recursion.

Bonus Challenge:

Testing All Methods:


Write a program test_fibonacci_methods() that tests the correctness and
performance of all three methods. This program should ensure that all methods return
the same results and should measure the time taken by each method to compute the
sequence for a large n , such as 30 or higher.

Number Guessing Game


In this assignment, you will create an interactive number guessing game using Python. The
program will generate a random integer within a specified range, and the user must guess the
number. After each guess, the program will inform the user if their guess is too high, too low, or
correct.

1. Random Number Generation:

Your program should generate a random integer between 1 and 100 (inclusive). Use
Python's random module for this purpose.

2. User Input:
The program should prompt the user to enter their guess. Ensure that the input is a
valid integer within the specified range.

3. Feedback Mechanism:

After each guess, the program should compare the user's guess to the generated
number and print:
"Too high" if the guess is higher than the number.
"Too low" if the guess is lower than the number.
"Correct! You guessed the number." if the guess is equal to the number.

4. Loop Until Correct Guess:

The game should continue, prompting the user for a guess until they correctly guess
the number.

5. User Interface:

Make sure the user interface is clear and user-friendly. Provide instructions to the user
on how to play the game.

6. Error Handling:

Your program should gracefully handle any input errors without crashing.

Bonus Challenge:

Guess Count:

Enhance your program to count the number of guesses the user makes. Display this
count when the user correctly guesses the number.

Range Customization:

Allow the user to specify the range within which the random number is generated (e.g.,
1 to 50, or 1 to 200).
Introduction to Programming
Strings

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Overview

• Structure of programs
• Variables, Values, Types, Operations
• Functions, Scope
• Conditions, Return Values
• Recursion, Iteration
• Structure of data
• Sequences, Strings

1
Overview

• Sequences
• A string is a sequence, indexing
• The length of a sequence
• Slices (subsequences)
• Traversal
• Searching
• Counting
• Strings
• The in operator for strings
• Strings are immutable
• String methods
• String comparison

2
A String is a Sequence

• A string is a sequence of characters


• We can address elements in a sequence using brackets
• The expression in the brackets is the index
• The index indicates an offset from the start of the sequence, beginning with zero
• An index must be an integer, otherwise type error is raised

message = 'hello'
letter = message[0] # letter = 'h'
i = 0
letter = message[i + 1] # letter = 'e'
letter = message[2.5] # TypeError: string indices must be integers

3
Length

• We can use len(string) to get the length of a string


• Note that the index of the last letter is len(string) - 1

length = len(message)
last = message[length] # IndexError: string index out of range
last = message[length - 1] # last = 'o'

4
Negative Indices

• We can use negative indices


• These count backward from the end of the string

last = message[-1] # 'o'


before_last = message[-2] # 'l'
message[-6] # IndexError: string index out of range

5
Slicing

• A slice is a subsequence, e.g. a substring


• msg[m:n] addresses the subsequence starting at index m and ending at index n - 1
• Note that the end index is not included in the slice

slice = message[0:2] # 'he'


slice = message[2:5] # 'llo'

6
Slicing

• Omitting the start index sets the start index to zero


• Omitting the end index sets the end index to len(string)
• It is possible to omit both, yielding [0:len(string - 1)]

slice = message[:2] # 'he'


slice = message[2:] # 'llo'
slice = message[:] # 'hello'

7
Slicing

• An end index larger or equal to the start index yields an empty string

slice = message[3:3] # ''


slice = message[3:2] # ''

8
Slicing

• We can use negative indices


• We can jump using a third ’argument’ to the slicing operator

slice = message[-3:-1] # 'll'


slice = message[0:len(message):2] # 'hlo'
slice = message[::2] # 'hlo'

9
Traversal

• We can traverse a sequence by index using a while loop

index = 0
while index < len(message):
letter = message[index]
print(letter)
index = index + 1

10
Traversal

• We can traverse a sequence by elements using a for loop

for letter in message:


print(letter)

11
Traversal

• We can also traverse a sequence by index using a for loop

message_length = len(message)
for index in range(message_length):
letter = message[index]
print(letter)

12
Search

• A typical pattern of computation: searching an element in a sequence


• Here, we return the index of the element if found, -1 otherwise
• Check this with pythontutor

def search(word, letter):


index = 0
while index < len(word):
if word[index] == letter:
return index
index = index + 1
return -1

13
Count

• Another pattern: Counting particular elements in a sequence


• Check this with pythontutor

word = 'banana'
count = 0
for letter in word:
if letter == 'a':
count = count + 1
print(count)

14
The in Operator

• in is a boolean operator that takes two strings and returns True if the first
appears as a substring in the second

'a' in 'banana' # True


'seed' in 'banana' # False

def in_both(word1, word2):


for letter in word1:
if letter in word2:
print(letter)

15
Strings are Immutable

• Strings are immutable: You cannot change an existing string object


• Rather, you have to create a new object

greeting = 'Hi there!'


greeting[0] = 'J'
# TypeError: 'str' object does not support item assignment
new_greeting = 'J' + greeting[1:]
# new_greeting is now 'Ji there!'

16
String Methods

• Strings provide many useful methods


• https://docs.python.org/3/library/stdtypes.html#string-methods
• Some methods provide optional arguments, e.g. from where to start looking
• Optional arguments are denoted by brackets in the documentation:
https://docs.python.org/3/library/stdtypes.html#str.find

hello = 'hi there'


big_hello = hello.upper() # 'HI THERE'
index = hello.find('i') # 1
index = hello.find('ere') # 5
index = hello.find('i', 3) # -1, as 'there' does not contain 'i'

17
String Comparison

• We can compare strings with comparison operators


• They adhere to lexicographic order
• All the uppercase letters come before all the lowercase letters
if word < 'banana':
print('Your word, ' + word + ', comes before banana.')
elif word > 'banana':
print('Your word, ' + word + ', comes after banana.')
else:
print('All right, bananas.')

'banana' < 'beta' # True


'Zeppelin' < 'abc' # True
'zeppelin' < 'abc' # False

18
Reading Data from Files

• We can read data from files

f = open("./traffic.txt")

for i in range(100):
line = f.readline()
print(line)
# we can do something with line

for line in f:
# we can do something with line

19
Reading Data from Files

• We have to provide absolute file paths, or relative to the current working directory
• Python’s operating system module os offers a method to get the current working
directory

import os
print(os.getcwd())

20
1 Palindrome
A palindrome is a word or sentence that reads the same forward and backward, e.g. ’never odd
or even’: https://en.wikipedia.org/wiki/Palindrome
• Write a function is_palindrome(some_string) that takes a string as argument, and that
returns a boolean indicating whether the given string is palindromic. Write the function
using (a) a for or while loop and (b) recursion.
• Bonus: Using slices and negative step sizes, there is a single line solution to this problem.
Can you find it?

2 Traffic Analytics
Download the traffic.txt file from the moodle page. It contains a toy dataset of traffic observa-
tions. Each observation is placed in a separate line. An observation looks like e.g.

06 >=>=======>=========

The first two characters indicate the hour of measurement, and the following characters
indicate the traffic measurement, ’=’ denoting an empty street segment, and ’>’ denoting a car.
• Write a function average_cars_at_hour(filepath, hour) that takes a filepath string
and a string indicating an hour as arguments, and that returns the average number of
measured cars at that hour.
• Write a function nr_of_empty_measurements(filepath) that takes a filepath string as
argument, and that returns the average number of measurements not containing any car.
• Write a function maximum_traffic(filepath) that takes a filepath string as argument,
and that returns the maximum number of cars present at any single measurement in the
dataset.
• Write a function nr_of_jams(filepath) that takes a filepath string as argument, and
that returns the number of jams present in the dataset measurements. A jam is defined
as at least three cars occupying consecutive street segments (i.e. '>>>' is a jam).
• Bonus: Can you write a function that finds the longest jam (i.e. sequence of consecutive
'>'s) present in the dataset?

3 In case you are looking for more exercises


You can find additional exercises on strings here: https://greenteapress.com/thinkpython2/
html/thinkpython2009.html#sec104

1
Introduction to Programming
Lists

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Overview

• Structure of programs
• Variables, Values, Types, Operations
• Functions, Scope
• Conditions, Return Values
• Recursion, Iteration
• Structure of data
• Sequences, Strings
• Lists

1
Overview

• A list is a sequence
• Filter, map, reduce
• Deleting elements
• Mutability, aliasing, cloning
• List arguments, modification vs. creation
• Addendum: Concurrent modification
• Addendum: Nested lists

2
A List is a Sequence

• A list can contain any values as elements, even other lists


• We can use all the sequence operations (cf. lecture on strings)
• Indexing, getting length, slicing and traversal work as with strings

a_list = []
a_list = [1, 2]
a_list = [1, 2, 'bob']
a_list[2] # -> 'bob'

3
Lists are mutable

• We can assign values to individual list elements


• Lists are ’mutable’ (in contrast to e.g. strings)

a_list = [1, 2, 'bob']


a_list[2] = 'alice'
# a_list -> [1, 2, 'alice']

4
Traversing a list

• Traversal works as with strings

a_list = [1, 2, 3]

for element in a_list:


print(element)

for i in range(len(a_list):
print(a_list[i])

5
List operations

• Addition/concatenation, multiplication and slicing work as with strings

a_list = [1, 2] * 2 # a_list -> [1, 2, 1, 2]


a_list = [1] + [2, 3] # a_list -> [1, 2, 3]
a_list[1:] # -> [2, 3]

6
List methods

• Append, extend
• Sort, reverse
• Most list methods operate in-place, and return None
• https:
//docs.python.org/3/tutorial/datastructures.html#more-on-lists

7
List methods

• Append, extend

# adding an element
a_list = []
for i in range(5):
a_list.append(i + 1)
print(a_list)

# concatenating a list
a_list = [1, 2]
a_list.extend([3, 4])
print(a_list)

8
List methods

• Sort, reverse
string_list = ['bob', 'ana', 'tim', 'beate']
string_list.sort() # remember lexicographic ordering
print(string_list)
mixed_list = [1, 2, 'bob', 'tim']
# mixed_list.sort() # causes a type error
# -> TypeError: '<' not supported between instances of 'str' and 'int'

# reverse
a_list = [1, 2, 3, 'ana']
a_list.reverse()
print(a_list)

9
Filter, map, reduce

• Filter: Get all elements from a list that satisfy a given condition
• Map: Apply a function/operation to each element of a list
• Reduce: Combine the elements of a list to a single value, e.g. sum, max, average,
count, search, ...

10
Filter

• Filter: Get all elements from a list that satisfy a given condition

original_list = [1, 2, 3, 4, 5, 6]
filtered_list = []
for element in original_list:
# filter condition
if element < 4:
filtered_list.append(element)
print(filtered_list)

11
Map

• Map: Apply a function/operation to each element of a list


# creating a new list
mapped_list = []
for element in original_list:
mapped_element = element ** 2 # mapping operation
mapped_list.append(mapped_element)
print(mapped_list)

# mapping in place, modifying the original list


for index in range(len(original_list)):
element = original_list[index]
element = element ** 2
original_list[index] = element
print(original_list)

12
Reduce

• Reduce: Combine the elements of a list to a single value, e.g. sum, max, average,
count, search, ...

original_list = [1, 2, 3]
reduced_value = 0
for element in original_list:
reduced_value += element
print(reduced_value)

13
Deleting elements

• We can delete elements from lists by element or by index


• Note that some operations change the argument list, while others leave the
argument unchanged and instead return a new list with the element(s) removed

element = the_list.pop(index)
the_list.remove(element)
del the_list[index]
del the_list[start:end]

14
Lists and strings

• We can convert from string to list and from list to string

some_string = 'hi ho'


character_list = list(some_string)
# character_list -> ['h', 'i', ' ', 'h', 'o']
word_list = some_string.split()
# word_list -> ['hi', 'ho']
delimiter = ' '
some_string = delimiter.join(word_list)
# some_string -> 'hi ho'

15
Objects and values

• In python, variables point at objects


• We can check whether two variables point to the same object (i.e. they are
aliases) using the is operator
• Lists behave differently from the types that we have seen so far (integer, float,
string, boolean)
a = 'word'
b = 'word
a is b # True
a = 1
b = 1
a is b # True
a = [1, 2]
b = [1, 2]
a is b # False <- !

16
Aliasing

• A list can be assigned to multiple variables with different names


• Changing the list changes the value of all assigned variables
• This is called aliasing

a = [1, 2]
b = a
a is b # True
b[0] = 42 # a -> [42, 2], b -> [42, 2]

17
Aliasing and copying

• We can copy a list to avoid aliasing

a = [1, 2]
b = a[:]
a is b # False
b[0] = 42 # a -> [1, 2], b -> [42, 2]

18
Mutable objects and scope

• Adding/removing/changing list elements has an effect in current and enclosing


scopes, up to the scope where the list has been defined
• Assigning new lists to variables only affects the current scope
def delete_head(t):
del t[0] # modifies list element -> effect in all scopes
letters = ['a', 'b', 'c']
delete_head(letters)
# letters -> ['b', 'c']

def set_tail(x):
x = x[1:] # assigns new list to variable -> effect in local scope only
x = [1, 2]
set_tail(x)
# x -> [1, 2]

19
Mutable objects and scope

• If the list is created in current scope, changing elements only has a local effect

def set_tail(x):
x = x[1:] # assigns new list to variable -> effect in local scope only
x[0] = 0
# x -> [0]
x = [1, 2]
set_tail(x)
# x -> [1, 2]

20
Modify vs. create

• Always be clear whether a function/method modifies the list in place, or creates a


new list

t1 = [1, 2]
t2 = t1.append(3)
# t1 -> [1, 2, 3]
# t2 -> None

t3 = t1 + [4]

21
Modify vs. create

• Also for your own code: Always be clear whether you modify the list in place, or
create a new list
• When creating a new list in function scope, you may consider to return it to the
caller
def bad_tail(t):
t = t[1:]
# Works, but probably not as expected
# (i.e. does not change t outside the function)

def tail(t):
return t[1:]

list_tail = tail([1, 2]) # -> [2] 22


Addendum: Concurrent modification

• Adding/removing elements to/from a list while iterating may cause confusing


behavior
• This is because adding/removing elements changes the indices of other list
elements
a = [1, 2, 3, 4]
for element in a:
a.remove(element)
print(a)

for index in range(len(a)):


print(a)
del a[index]
23
Addendum: Concurrent modification

• Iterating over a copy of the list to be modified may mitigate the problem

list_of_num = [1, 2, 3, 4, 5, 6]
for elem in list_of_num:
if elem == 3 or elem == 4:
list_of_num.remove(elem)
print(list_of_num) # -> [1, 2, 4, 5, 6]

list_of_num = [1, 2, 3, 4, 5, 6]
for elem in list_of_num[:]: # make a copy using [:] for iteration
if elem == 3 or elem == 4:
list_of_num.remove(elem) # remove from original list
print(list_of_num) # this works as expected: -> [1, 2, 5, 6]

24
Addendum: Concurrent modification

• Alternatively, create a new list to keep the (intermediate and final) results while
iterating over the original list

def filter_list(a_list, n):


filtered_list = []
for element in a_list:
if not element < n:
filtered_list.append(element)
return filtered_list

25
Addendum: Nested lists

• List can be elements of other lists


• For example, we can represent 2D grids with nested lists
• Maybe useful for board games or matrix operations :)
nr_rows = 3
nr_cols = 3

# generate the grid row by row


grid = []
for x in range(nr_cols):
row = []
for y in range(nr_rows):
row.append((x, y))
grid.append(row)

# access grid rows and elements


for row in grid:
print(row)
print(grid[1][2])

26
1 Warm Up
• Write a function called nested_sum that takes a list of lists of integers and adds up the
elements from all of the nested lists. For example:
t = [[1, 2], [3], [4, 5, 6]]
nested_sum(t) # -> 21
• Write a function called middle that takes a list and returns a new list that contains all
but the first and last elements. For example:
t = [1, 2, 3, 4]
middle(t) # returns [2, 3]
• Write a function called chop that takes a list, modifies it by removing the first and last
elements, and returns None. For example:
t = [1, 2, 3, 4]
chop(t) # returns None
# t -> [2, 3]
• Write a function filter_list(a_list, n) that creates a new list containing all elements
from a_list that are smaller than n. For example:
a_list = [4, 6, 4]
filter_list(a_list, 5) # -> [6]
a_list = [3, 5, 1, 2]
filter_list(a_list, 3) # -> [1, 2]

2 Anagrams
• Two words are anagrams if you can rearrange the letters from one to spell the other.
Write a function called is_anagram that takes two strings and returns True if they are
anagrams.
is_anagram('elvis', 'lives') # -> True
is_anagram('roses', 'are trees') # -> False

3 Buffer
• Initialize a variable a_buffer to an empty list.
• Write a function process(a_buffer, x) that appends x to the a_buffer. If a_buffer
contains more than three elements, also remove its first element (i.e. the element at
index zero).

4 List arguments
What does the following program print? Why? Try to predict what the program does before
executing it. Also, step through this program using pythontutor.

1
def f(x):
x = x + [3]

def g(x):
x = x + [3]
return x

def h(x):
x[0] = 0

x = [1, 2]
f(x)
print(x)
x = g(x)
print(x)
h(x)
print(x)

5 Aliasing
What does the following program print? Why? Try to predict what the program does before
executing it. Also, step through this program using pythontutor.
def f(x):
x = x + [3]

def f2(x):
x.append(3)

x = [1, 2]
y = x
f(x)
print(x, y)
f2(x)
print(x, y)
y = x[:]
f2(x)
print(x, y)

6 In case you are looking for more exercises


You can find additional exercises on lists here: https://greenteapress.com/thinkpython2/
html/thinkpython2011.html#sec128

2
Exercise: Building a Console Tic-Tac-Toe Game in Python

Sub-Exercise 1: Setting Up the Game Board

1. Objective: Create a 3x3 game board using a list of lists.


2. Tasks:
Initialize a 3x3 list with empty strings or a placeholder character.
Write a function print_board(board) that prints the board to the console.

Sub-Exercise 2: Player Input

1. Objective: Allow players to input their moves.


2. Tasks:
Create a function player_move(board, player) that takes the board and the current
player's symbol ('X' or 'O') as arguments.
Prompt the player to enter row and column numbers to place their symbol.
Check if the chosen cell is empty and update the board accordingly.

Sub-Exercise 3: Checking for a Win

1. Objective: Implement logic to check for a winning condition.


2. Tasks:
Write a function check_win(board) that returns True if there's a winning condition
(three in a row, column, or diagonal).
After each move, call this function to determine if the current player has won.

Sub-Exercise 4: Checking for a Draw

1. Objective: Identify if the game has ended in a draw.


2. Tasks:
Modify the check_win(board) function to also check if the board is full and no player
has won, indicating a draw.

Sub-Exercise 5: Switching Between Players

1. Objective: Alternate turns between two players.


2. Tasks:
Implement a way to switch the current player after each valid move.

Sub-Exercise 6: Main Game Loop


1. Objective: Combine all the components into a main game loop.
2. Tasks:
Set up a loop that continues until the game ends (either win or draw).
Call the appropriate functions to handle player input, update the board, and check
game status.

Sub-Exercise 7: Adding User-Friendly Features

1. Objective: Improve user experience.


2. Tasks:
Add clear instructions for the players.
Implement input validation and error handling.
Introduction to Programming
Dictionaries

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Overview

• Structure of programs
• Variables, Values, Types, Operations
• Functions, Scope
• Conditions, Return Values
• Recursion, Iteration
• Structure of data
• Sequences, Strings
• Lists
• Dictionaries

1
A dictionary is a mapping

• A dictionary maps keys to values


• Like lists, but indices are not restricted to be integers

d = {} # empty dictionary
d['one'] = 1
d['two'] = 2

print(d)
print(d['one']) # -> 1

2
Basic operations

• We can iterate the keys with a for loop


• We can access keys and values with built-in methods
• We can query the number of items using len
• in checks whether the given key is present in the dictionary
for key in d:
print(key)

print(d.keys())
for element in d.values():
print(element)

print(len(d))

key_is_present = 'one' in d
print(key_is_present) 3
Under the hood

• Python dictionaries implement a hashtable


• Hashtables allow for efficient lookup of entries
• For more infos on hashtables, see
https://en.wikipedia.org/wiki/Hash_table
• We can query the hash of a hashable object using hash
• Only immutable types can be hashed

print(hash('hello'))
print(hash([1, 2])) # -> TypeError: unhashable type: 'list'

4
Example: Histogram

• We can implement a histogram of characters using a dictionary


• This illustrates a pattern: Create or update
def histogram(message):
d = {}
# for each character, create or update entries in dictionary
for character in message:
# if the character is not already in the histogram, *create* it
if not character in d:
d[character] = 1
# otherwise (if it is already there), *update* the value
else:
d[character] = d[character] + 1
return d

hist = histogram('hello there')


5
Example: Inverted Histogram

• The example histogram maps each character to a single integer


• If we invert this mapping (integer to character), one key may yield multiple values
• So we implement values as lists

inverted_hist = {} # int -> list of character


# again: create or update, this time with list elements as values in the dictionary
for character in hist:
number_of_occurences = hist[character]
if not number_of_occurences in inverted_hist: # not there? -> create list value
inverted_hist[number_of_occurences] = [character]
else: # already there -> append character to list
inverted_hist[number_of_occurences].append(character)

6
1 Inventory
This exercise is based on: https://erlerobotics.gitbooks.io/erle-robotics-learning-python-gitbook-free/
content/lists/exercises_list_and_dictionaries.html

Given the following dictionary:

inventory = {
'gold': 5,
'pouch': ['ruby', 'emerald', 'diamond'],
'backpack': ['xylophone', 'book', 'bedroll','bread loaf']
}

Implement the following operations, and observe their effect in pythontutor.

• Add a key to inventory called ’pocket’. Set the value of ’pocket’ to be a list consisting of the strings
’seashell’, ’strange berry’, and ’lint’.
• Sort the items in the list stored under the ’backpack’ key.
• Remove ’bread loaf’ from the list of items stored under the ’backpack’ key.
• Add 2 to the number stored under the ’gold’ key.

Implement a function sort(dict) that sorts every value that is of type list for a given dictionary. Use sort(inventory)
to sort the inventory.
Implement a function to_stock that takes a pouch list (of strings) as an argument and returns a dictionary
mapping items (strings) to their number of occurrences.

pouch = ['ruby','emerald','ruby','diamond','diamond']
stock = to_stock(pouch)
# stock -> {'ruby': 2, 'emerald': 1, 'diamond': 2}

Create a dictionary called prices. Put these key-value pairs in your prices dictionary:

"ruby": 2, "emerald": 1, "diamond": 3

Write a function pouch_value(inventory_dict, prices_dict) returning an integer that indicates how much
you would make from selling the pouch of the given inventory, assuming the given prices.

2 Inversion
Given a dictionary that maps a number to a list of characters, implement a function that inverts this dictionary.
You can assume that each character only occurs once in the given dictionary values.

dict = {1: ['a', 'b'], 2: ['c'], 3: ['d', 'e']}


inverted_dict = invert(dict)
# inverted_dict -> {'a': 1, 'b': 1, 'c': 2, 'd': 3, 'e': 3}

More difficult variant: Implement invert, assuming a character can appear more than once in the values.

dict = {1: ['a', 'b'], 2: ['a'], 3: ['a', 'c']}


inverted_dict = invert(dict)
# inverted_dict -> {'a': [1, 2, 3], 'b': [1], 'c': [3]}

1
3 Decode Cipher
Consider the cipher from the lecture (see code below). Implement a function decode(encoded_message, cipher)
to recover the original message.

import string
from random import shuffle

# create the cipher


keys = list(string.ascii_lowercase + string.ascii_uppercase + string.digits)
mapping = keys[:]
shuffle(mapping)
cipher = {}
for key, value in zip(keys, mapping):
cipher[key] = value

# apply the cipher to encode a message


def encode(message, cipher):
encrypted_message = ''
for character in message:
if character in cipher:
encrypted_character = cipher[character]
else:
encrypted_character = character
encrypted_message += encrypted_character
return encrypted_message

# test the cipher encoding


message = 'hello there, how are you doing? it is a lot of python here'
encoded_message = encode(message, cipher)

4 In case you are looking for more exercises


You can find additional exercises on lists here: https://greenteapress.com/thinkpython2/html/thinkpython2012.
html#sec139

2
Introduction to Programming
Tuples and Files

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Overview

• Structure of programs
• Variables, Values, Types, Operations
• Functions, Scope
• Conditions, Return Values
• Recursion, Iteration
• Structure of data
• Sequences, Strings
• Lists
• Dictionaries

1
Overview

• Tuples
• Tuple assignment
• As keys in dictionaries
• Gather, scatter
• Tuples as return values
• zip and enumerate
• Reading and writing files
• Pickle

2
Tuples

• Tuples are immutable sequences


• Similar to lists, but we cannot change them

t = (1, 2, 'three')
t[1] # -> 2
t[1] = 'one'
# -> TypeError: 'tuple' object does not support item assignment

empty_tuple = tuple()
tuple_with_one_element = (1,)

3
Tuple assignment

• We can use tuples to assign multiple values at once


• Example: swap values

a = 0
b = 1
a, b = b, a # tuple assignment: a -> 1, b -> 0

# this does not swap values


a = 0
b = 1
a = b # a -> 1
b = a # b -> 1

4
Tuples as dict keys

• As tuples are immutable, we can use them as keys in dictionaries

game_board = {}
for x in range(3):
for y in range(3):
game_board[(x, y)] = 0

5
Scatter

• We can scatter function arguments using the asterisk when calling a function

def add(a, b, c):


return a + b + c

t = (1, 2, 3)
add(*t) # -> 6
add(t)
# -> TypeError: add() missing 2 required positional arguments: 'b' and 'c'

6
Scatter

• We can gather function arguments using the asterisk when defining a function

def add(*args):
arg = 0
for arg in args:
value += arg
return value

add(1, 2, 3) # -> 6
add(1, 2, 3, 4) # -> 10

7
Tuples as return values

• We can use tuples to return multiple values from a function

def swap(a, b):


return b, a

x, y = swap('hi', 'there')
# x -> 'there, y -> 'hi'

8
Zip

• We can iterate over two lists ’in parallel’, in a sense iterating over a list of tuples
• We can use zip to do this
• The shorter list defines the length of the iteration

number_list = [11, 2, 8]
char_list = ['a', 'b', 'c', 'd']
for number, char in zip(number_list, char_list):
print(number, char)
# prints '11 a', '2 b', and '8 c'

9
Enumerate

• We can iterate over elements and keep track of the index at the same time using
enumerate

for i, char in enumerate(char_list):


print(i, char)
# prints '0 a', '1 b','2 c', and '3 d'

# longer alternative
i = 0
for char in char_list:
print(i, char)
i += 1

10
Reading Files

• We can open a file using open


• The path is either absolute, or relative to the current working directory
• We can use os.getcwd() to get the current working directory

import os
print(os.getcwd())

file = open('./datafiles/iris.data')
print(file)

11
Reading Files

• We can read a file line by line using a for loop

file = open('./datafiles/iris.data')
for line in file:
print(line)

12
Writing Files

• We can write to a file by setting the mode when opening it


• ’r’: read only
• ’x’: create a writable file, raises an error if it already exists
• ’a’: append written data to the existing file
• ’w’: overwrite file contents

file = open('./ourfile.data', mode='w')


for i in range(2):
file.write('hi there')
file.write('\n')
file.close()

13
Pickle

• We can store python objects to files using pickle


• We need to use modes ’wb’ (write bytes) and ’rb’ (read bytes) when writing or
reading pickled objects to/from files
import pickle

file = open('./our_dict.data', mode='wb')


our_dict = {'a': 1, 'b': 'hello'}
pickle.dump(our_dict, file)

file = open('./our_dict.data', mode='rb')


reloaded_dict = pickle.load(file)
print(reloaded_dict)
14
Introduction to Programming
Classes and Objects

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Overview

• Structure of programs
• Variables, Values, Types, Operations
• Functions, Scope
• Conditions, Return Values
• Recursion, Iteration
• Structure of data
• Sequences, Strings
• Lists
• Dictionaries
• Tuples
• Utilities
• Files

1
Classes

• We can define classes for organizing data and code in namespaces


• We can create instances of a class calling Classname()
• When creating an instance, the classes’ constructor __init__ is interpreted

class Car:
def __init__(self):
print('hi, I am a new car')

car = Car()
# creates a Car object assigned to car
# prints 'hi, I am a new car'

2
Attributes

• We can organize data of a class by defining its attributes


• We can define and access attributes using the dot notation

class Car:
def __init__(self):
self.velocity = 0

car = Car()
car.velocity # -> 0

3
Attributes

• We can parametrize class constructors

class Car:
def __init__(self, v):
self.velocity = v

car = Car(100)
car.velocity # -> 100

4
Methods

• We can define functions inside a class to organize code in namespaces


• These functions are called methods
• We can call methods using the dot notation
class Car:
def __init__(self, v):
self.velocity = v

def accelerate(self):
self.velocity += 1

car = Car(100)
car.velocity # -> 100
car.accelerate()
car.velocity # -> 101

5
Self

• The first parameter of a method (self by convention) refers to the object the method is called on
• This means self points to the object before the dot
• This also means that we have to pass one less argument to the method that it has parameters in
the definition (because self is already assigned)

class Car:
def __init__(self, v):
self.velocity = v

def accelerate(self):
self.velocity += 1

car = Car(100)
car.velocity # -> 100
car.accelerate()
car.velocity # -> 101
6
Objects are Mutable

• Objects are mutable (as e.g. lists)

def stop(car):
car.velocity = 0

car = Car(100)
stop(car)
car.velocity # -> 0

7
Combining Objects

• We can use any object as attributes


class Point2D:
def __init__(self, x, y):
self.x = x
self.y = y

class Line:
def __init__(self, start, end):
self.start = start
self.end = end

line = Line(Point2D(0, 0), Point2D(1, 1))


8
1 Edabit
Tackle the following Edabit challenges. Inspect your results using pythontutor.
• Food for Everyone: https://edabit.com/challenge/iRvRtg2xxL9BnSEvf
• Older Than Me: https://edabit.com/challenge/JFLADuABfkeoz8mqN
• Simple OOP Calculator: https://edabit.com/challenge/ta8GBizBNbRGo5iC6

2 Statements
Create a class Statement that represents a programming statement. It has two attributes:
• command is a string and contains the statement’s command, e.g. 'move', 'turn', etc.
• arguments is a sequence of values that parametrize the statement, e.g. (10, 50).
Create a constructor for the Statement class that takes as parameters a) the command and b)
any number of statement arguments. You may consider gathering the arguments using * as
discussed in the lecture. Don’t forget to add the self parameter to the constructor.
s0 = Statement('move', 10, 50)
print(s0.command) # prints 'move'
print(s0.arguments) # prints (10, 50)
Create a method interpret in the Statement class that prints the command and its arguments.
For example, if command is 'move' and arguments are '(10, 50)', print 'move 10 50'. Don’t
forget to add the self parameter to the method definition.
s0 = Statement('move', 10, 50)
s0.interpret() # prints 'move 10 50'
s1 = Statement('turn', 45)
s1.interpret() # prints 'turn 45'

3 Programs
Create a class Program that has a list of Statement as attributes. Define a constructor that takes
no arguments and initializes an empty list of statements.
p = Program()
print(p.statements) # prints []
Define a method append in the Program class that takes a statement as parameter and appends
it to the list of statements of that program.
p = Program()
p.append(s0)
p.append(s1)
print(len(p.statements)) # prints 2
print(p.statements[0].command) # prints 'move'
Create a method interpret in class Program that calls the interpret method on all statements
in the program’s statement list.

1
4 Parsing
Create a method parse in class Program that takes a program string containing one statement
written as a string per line, creates a Statement object for each line, and adds the statement to
the program’s statement list.
p = Program()
p.parse('move 1 2\nturn 90')
p.interpret()
# prints move 1 2
# prints turn 90
Can you load, parse and interpret a program that is written in a file?

5 In case you are looking for more exercises


Check out the exercises using the ’classes’ tag at Edabit: https://edabit.com/challenges/
python3

2
Introduction to Programming
Inheritance

Lenz Belzner
Based on Think Python 2nd Edition by Allen B. Downey
Overview

• Structure of programs
• Variables, Values, Types, Operations
• Functions, Scope
• Conditions, Return Values
• Recursion, Iteration
• Structure of data
• Sequences, Strings
• Lists
• Dictionaries
• Tuples
• Utilities
• Files
• Classes
• Inheritance
1
Inheritance

• We can create class hierarchies using inheritance


• It is a way to structure data and code in complex application domains
• Inheritance enables code reuse and maintainability

2
Inheritance

class General:
def __init__(self):
self.name = 'general'

def general_method(self):
print('I am ' + self.name + '.')

class Special(General):
def special_method(self):
print('I am' + self.name + ', but special.')

special = Special()
special.general_method() # prints 'I am general.'
special.special_method() # prints 'I am general, but special.'

3
Inheritance

• More specific classes (’subclasses’) inherit from more general classes


(’superclasses’)
• Subclasses have all code from their superclasses available, without explicitly
defining it again
• See lecture code for examples!

4
super

• We can add more properties to a subclass in the constructor


• In this case, we have to invoke the superclass constructor explicitly
class General:
def __init__(self):
self.name = 'general'

class Special(General):
def __init__(self):
super().__init__()
self.additional_attribute = 'special'

def special_method(self):
print('I am ' + self.name + ', but ' + self.additional_attribute + '.')

special = Special()
special.special_method() # prints 'I am general, but special.' 5
super

• We may need to pass arguments to the constructor of the superclass


class General:
def __init__(self, name):
self.name = name

class Special(General):
def __init__(self, name):
super().__init__(name)
self.additional_attribute = 'special'

def special_method(self):
print('I am ' + self.name + ', but ' + self.additional_attribute + '.')

special = Special('general')
special.special_method() # prints 'I am general, but special.'
6
Association

• We can also organize code by making objects of one class an attribute of another

class Vehicle:
# class code omitted for brevity

class Tire:
# class code omitted for brevity

class Car(Vehicle):
def __init__(self, tire):
super().__init__()
self.tire = tire

car = Car(Tire())

7
1 Statements and Expressions
1.1 Values, Types, Operations and Precedence
Consider the following python program.

a = 3 ** 2 // 2
b = ('h' + str(1)) * 2
c = 'h' + str(1) * 2
d = ['hi'] * 2
e = ['hi' * 2]
f = 1 < 2 or 2 ** 2 > 1 ** 1

What are a) the value and b) the type of a, b, c, d, e and f?

1.2 Dictionaries, Lists, Loops and Conditions


Consider the following python program.

store = {'water': 2, 'bread': 1, 'tomatoes': 3, 'wheat': 0}

filtered_data = []
for element in store:
if store[element] > 0:
filtered_data.append(store[element])
elif store[element] < 0:
filtered_data = []

After interpretation of the program:


1. What is a) the value and b) the type of store['water']?
2. What is a) the value and b) the type of filtered_data?
3. What is a) the value and b) the type of len(filtered_data)?
4. What is a) the value and b) the type of filtered_data[1]?

1
2 Functions, Patterns
2.1 Average
Implement a function average(l) that computes and returns the average value of elements in
a list. You can assume the list contains at least one element, and that all elements in the list are
integers.

# Examples
average([1, 2]) # -> 1.5
average([-1, 1, -1, 1]) # -> 0.0

2.2 Check
Implement a function check(l) that returns True if the list argument contains at least one
element, and all elements in it are integers, and that returns False otherwise. You can assume
the argument is always a list.

# Examples
check([1, 2]) # -> True
check([1, 'hello']) # -> False
check([]) # -> False

2.3 Check and Average


Implement a function check_and_average(l) that takes a list argument, checks whether the
list is non-empty and contains only integers, prints 'Please check your list.' if it does not,
and returns the average value of list elements otherwise. Use can use check and average for
your implementation, even in case you did not provide an implementation for them.

# Examples
check_and_average([1, 2]) # -> 1.5
check_and_average([1, 'hello']) # -> None, prints 'Please check your list.'
check_and_average([]) # -> None, prints 'Please check your list.'

2
3 Loops, Recursion
3.1 Recursive Count
Consider the following program. You can assume message is a string, and character is a string
containing a single character.

def count(message, character):


index = 0
occurrences = 0
while index < len(message):
if message[index] == character:
occurrences += 1
index += 1
return occurrences

# Examples
count('hello there', 'e') # -> 3
count('hello there', 'o') # -> 1
count('hello there', 'a') # -> 0

Implement a recursive version recursive_count(message, character) of count, implement-


ing a base case and at least one recursive case. Hint: You know the character count for any
character for the empty string. Your implementation must not use a for-loop or a while-loop,
and must not use the string method count().

# Examples
recursive_count('hello there', 'e') # -> 3
recursive_count('hello there', 'o') # -> 1
recursive_count('hello there', 'a') # -> 0

3
4 Strings
4.1 Remove Vowels
Implement a function remove_vowels(message) that takes a string as an argument, and returns
a string with all vowels (’a’, ’e’, ’i’, ’o’, ’u’) removed. You can assume the argument is a string.

# Examples
remove_vowels('hello there') # -> 'hll thr'
remove_vowels('') # -> ''

4.2 Sorted List of Strings


Implement a function is_sorted(string_list) that takes a list of strings as argument, returns
True if it is sorted in ascending lexicographical order, and False otherwise. You can assume
that the list only contains elements of type string, that it contains at least two elements, and
that each string only occurs once in the list.

# Examples
is_sorted(['hello', 'there']) # -> True
is_sorted(['hello', 'again']) # -> False
is_sorted(['all', 'blues', 'miles', 'music']) # -> True

4
5 Classes and Objects
5.1 Colorful Bikes
Consider the following definition for class Tire.

class Tire:
def __init__(self, color):
self.color = color

def paint(self, color):


self.color = color

tire = Tire('magenta')
tire.paint('orange')
tire.color # -> 'orange'

Implement a class Bike with a constructor such that a bike object has a black front tire and a
black rear tire as attributes. A correct implementation should yield the following behaviour.

bike = Bike()
bike.front.color # -> 'black'
bike.rear.color # -> 'black'
bike.front is bike.rear # -> False

In class Bike, implement a method set_tire(self, tire, position) that replaces the bike’s
tire at the given position with the new tire passed as an argument. A correct implementation
should yield the following behaviour.

bike = Bike()
bike.set_tire(Tire('magenta'), 'front')
bike.front.color # -> 'magenta'
bike.set_tire(Tire('orange'), 'rear')
bike.rear.color # -> 'orange'

5
5.2 Object Diagram
Consider the following object diagram, omitting the class definitions for Tire and Bike. Write
minimal code that produces this diagram using the Bike and Tire classes.

6
6 Scope, Mutability, Aliasing
Consider the following program. What does it print?

def f(x):
x[0] += 1
print(x)

def g(x):
y = x
y[0] += 1
print(y)

def h(x):
y = x[:]
y[0] += 1
print(y)

x = [0, 1]
f(x)
print(x)

x = [0, 1]
g(x)
print(x)

x = [0, 1]
h(x)
print(x)

You might also like