Python Individualtraining (5 Tage, beginnend 28.10.2019)¶
Der Kurs nahm eine Woche in Anspruch, da hat so einiges Platz. Hier
die gesammelten Notizen inklusive Code; für schnell erklärte
Sachen gibts ein Jupyter Notebook (Download
).
Exercises¶
Slide 51, “Exercises: Basics”¶
Write a program that takes a single digit as commandline parameter. Print the English word for that digit.
#!/usr/bin/python3
# Exercises: Basics (~51)
# Write a program that takes a single digit as commandline
# parameter. Print the English word for that digit.
import sys
translation = {
0: 'zero',
1: 'one',
2: 'two',
3: 'three',
4: 'four',
5: 'five',
6: 'six',
7: 'seven',
8: 'eight',
9: 'nine',
}
digit = int(sys.argv[1])
if 0 <= digit <= 9:
print(translation[digit])
else:
print('nix')
Slide 58, “Exercises: While Loop”¶
Write a program that takes an integer commandline parameter and checks whether that number is prime!
#!/usr/bin/python3
# Exercises: While Loop (~58)
# Write a program that takes an integer commandline parameter and
# checks whether that number is prime!
# Exercises: Lists, Loops, Functions (~94)
# Modify the prime number detection program from one of the previous
# exercises: make the prime number detection a function, and call the
# function instead. The function (is prime() is a likely name) takes a
# number, and returns a boolean value as appropriate.
import sys
def is_prime(candidate):
if candidate < 2:
return False
divisor = 2
while divisor <= candidate//2:
if candidate % divisor == 0:
return False
divisor += 1
else:
return True
candidate = int(sys.argv[1])
print(is_prime(candidate))
Slide 94, “Exercises: Lists, Loops, Functions”¶
Write a function uniq() that takes a sequence as input. It returns a list with duplicate elements removed, and where the contained elements appear in the same order that is present in the input sequence. The input sequence remains unmodified.
#!/usr/bin/python3
# Exercises: Lists, Loops, Functions (~94)
# Write a function uniq() that takes a sequence as input. It returns a
# list with duplicate elements removed, and where the contained
# elements appear in the same order that is present in the input
# sequence. The input sequence remains unmodified.
# Deviations from the requirement:
# 1. implement uniq() as a generator. use yield to produce items.
# 2. demonstrate how to use uniq() as a filter, connecting nodes
# together using "pipes" as in the pseudo-filter expression:
# random | uniq | print
import random
def uniq(l):
'''filter that iterates over the input sequence and produces an item
only if that was not yet seen in the input sequence.
'''
have = set()
for i in l:
if i not in have:
have.add(i)
yield i
def randomnumbers(howmany):
"produces'howmany' random numbers."
for _ in range(howmany):
yield random.randrange(10)
for i in uniq(randomnumbers(100)):
print(i)
Slide 121, “Exercises: Strings”¶
Write a program that receives any number of arguments and prints them out right justified at column 20.
#!/usr/bin/python3
# Exercises: Strings (~121)
# Write a program that receives any number of arguments and
# prints them out right justified at column 20.
import sys
for s in sys.argv[1:]:
while len(s) >= 20:
print(s[:20])
s = s[20:]
print(s.rjust(20))
Miscellaneous¶
Famous Generator Introduction¶
Producing an infinite sequence (Fibonacci, what else)
#!/usr/bin/python3
# Generators, yield. implementing an infinite sequence (fibonacci is a
# cool example) which would not be so easy if we had only functions
# (these can only return once).
import time
def fibonacci():
prev = 1
cur = 1
yield prev
yield cur
while True:
next = prev + cur
yield next
prev = cur
cur = next
for fibonum in fibonacci():
print(fibonum)
eval()
: Convert a String into a Python Data Structure¶
During the uniq
exercise, people tend to want to pass a Python
list from the commandline, naively.
Question: how can I take an argument from the commandline (say,
sys.argv[1]
) and interpret that as a list?
Answer: eval
The following program does that. Call it like so,
$ ./eval-argv.py '[1, 2, 3, 4]'
(‘$’ is the shell prompt, the quotes are necessary to prevent the shell from splitting arguments at the spaces)
#!/usr/bin/python3
import sys
input_list_string = sys.argv[1]
input_list = eval(input_list_string)
print(input_list)
Operator Overloading¶
Here’s a little snippet that demonstrates this. See the docs for more.
#!/usr/bin/python3
# question: from C++ I know that I can overload (arithmetic) operators
# for types/classes that I define. how is this done in Python?
class Integer:
def __init__(self, n):
self.__n = n
@property
def n(self):
return self.__n
def __lt__(self, rhs):
return self.__n < rhs.__n
def __le__(self, rhs):
return not self > rhs
def __eq__(self, rhs):
return self.__n == rhs.__n
def __iadd__(self, n):
'iadd: +=, "in-place add"'
self.__n += n
return self
def __add__(self, n):
'add: +, called on self, the right hand "a" side in "a+b"'
new_number = self.__n + n
return Integer(new_number)
def __radd__(self, n):
'radd: +, called on the right hand side if the lhs does not support it'
new_number = n + self.__n
return Integer(new_number)
x = Integer(1)
y = Integer(2)
print('1<2', x < y)
print('2<1', y < x)
print('1>2', x > y)
print('1==1', x == x)
print('1!=1', x != x)
print('1<=2', x <= y)
print('1<=1', x <= x)
x += 1
print(x.n)
z = x + 1
print(z.n)
z = 1 + x
print(z.n)
Getters and Setters¶
Called “Properties” in Python; see below for a snippet. See the docs for more.
#!/usr/bin/python3
# question: in C# we have getters and setters. how is this done in
# Python?
# answer: use the property *decorator*
class MakesNoSense:
def __init__(self, number):
self.__number = number
@property
def number(self):
return self.__number
@number.setter
def number(self, n):
self.__number = n
num = MakesNoSense(42)
print(num.number)
num.number = 666
print(num.number)
More on Listcomprehensions and Generator Expressions¶
#!/usr/bin/python3
input_numbers = [1,2,3,4]
def squares(numbers):
'''return a list containing the squares of the numnbers from the input
sequence
'''
list_of_squares = []
for i in numbers:
list_of_squares.append(i**2)
return list_of_squares
print('dumb function: squares({})'.format(input_numbers))
for i in squares(input_numbers):
print(i)
# for such simple things as square numbers, use a list
# comprehension. this makes the code shorter - you omit a function
# definition.
print('list compehension: [n**2 for n in {}]'.format(input_numbers))
for i in [n**2 for n in input_numbers]:
print(i)
# list comprehensions still allocate memory to hold the list. with
# minimal effort, you can save that allocation by transforming the
# list comprehension into a generator expression.
print('generator expression: (n**2 for n in {})'.format(input_numbers))
for i in (n**2 for n in input_numbers):
print(i)
More on Local and Global Scope and Global Variables¶
#!/usr/bin/python3
# Functions: Local and Global Variables (~92)
def local_assignment():
'''assign to l in local scope. this creates a local variable
l. (variables are generally creates at first assignment.)
'''
l = 7
def read_global_variable():
'''accesses a variable g that has never been assigned to in local
scope. this goes out into the enclosing (global) scope and looks
it up there.
'''
print('read_global_variable: g =', g)
def local_shadows_global():
'''assign to g in local scope. this does *not* assign to the global
variable g, but creates a local variable g.
'''
g = 42
print('local_shadows_global: g =', g)
def explicit_global_assignment():
global g
print('explicit_global_assignment: before assignment g =', g)
g = 42
print('explicit_global_assignment: after assignment g =', g)
# first assignment to g in global scope creates g in global scope.
g = 666
local_assignment()
read_global_variable()
local_shadows_global()
print('global g =', g)
explicit_global_assignment()
print('global g =', g)
Closures: Between Local and Global¶
#!/usr/bin/python3
# closure: at the time of function creation (execution of the 'def
# statement), all referenced names are captured to form an
# intermediate scope, the 'closure'
def create_function(parameter):
loc = 42
# at this point, we have two variables in local scope - 'loc' and
# 'parameter'.
print('create_function: loc={}, parameter={}'.format(loc, parameter))
# with this in place, create a function object by executing the
# def statement. note how the function is not executed, but only
# created/compiled.
def inner_function():
# reference variables loc and parameter. these are defined
# neither in local nor in global scope. but they are found in
# the enclosing scope - the locals of create_function(), which
# forms an intermediate scope, the 'closure', whic his added
# to the lookup chain of inner_function().
print('parameter {}, loc {}'.format(parameter, loc))
return inner_function
f_one = create_function('one')
f_one()
f_two = create_function('two')
f_two()
Project¶
We had two days left, in addition to the usual three days which are sufficient to learn the basics. A group project was launched, with the somewhat real-life topic “talking to switches and doing all kinds of stuff with that information”.
This gave us the opportunity to discover a couple of areas more closely.
Object oriented programming (a switch has interfaces, and both have properties)
Storing all that in databases
Exception handling
Commandline interfaces
Unit testing