Python Grundlagen - Ein kurzes Tutorial¶
Python ist
eine universelle, moderne high-level Programmiersprache, die
verschiedene Programmierparadigmen ermöglicht:
- objektorientiert
- funktional
- aspektorientiert
Allgemeine Charakteristik / Ziele¶
- Ausdruckstark: Unterstützt das Schreiben von kurzem, klaren Programmcode.
- Komplexe(re) Datenstrukturen möglich bzw. eingebaut, wie Listen oder Maps (
dict
).
Weitere (technische) Details¶
- Dynamisch typisiert (dynamically typed)
- Automatische Speicherverwaltung (automatic memory management)
- in der Regel interpretiert, der Standard-Interpreter ist CPython (wird aber auch in Byte-Code kompiliert.)
- es gibt aber weitere Implementierungen von Python.
- Performanz-kritische (in Bezug auf die Laufzeit) Teile können in C/C++ entwickelt werden.
- es gibt aber auch Compiler:
- umfangreiche Bibliotheken für verschiedenste Anwendungsfälle
- insbesondere auch im Bereich Data Science, Machine Learning, Artificial Intelligence weit verbreitet.
Python Style Guide¶
Sauberer Pythoncode folgt einem vorgegeben Stil, der in einem "Python Enhancement Proposals" pep beschrieben ist: https://www.python.org/dev/peps/pep-0008
Tipp: Verwenden Sie von Beginn an einen Type-Checker, um den von Ihnen entwickelten Code zu überprüfen, z.B. Style-Checker für jupyter notebooks.
#%load_ext pycodestyle_magic
#%pycodestyle_on
Variablen¶
Variablen sind Namen, die auf einen Wert, eine Funktion oder ein Objekt zeigen:
a_string = "hello, world"
an_integer = 12
a_float = 3.14
a_boolean = True
Beachte die dynamische Typisierung: Variablen haben explizite Typen. Diese werden bei der Zuweisung automatisch erkannt.
type(an_integer)
int
Typumwandlungen (cast)¶
# Convert a string to an integer and vice-versa:
i = 12
s = str(i)
type(s)
str
Print¶
Einfache Ausgabe via print
print("hello, world")
print(12)
print((5+3)/2)
hello, world 12 4.0
# This is a comment.
# To print several items,
# use commas (items will be separated by spaces):
print("abc", 12, a_float)
# multiline is possible, if there are braces
print('multiline is possible,'
' if there are braces')
multiline = 'a long statement may be split using backslash',\
'this is still the same statement',\
'the end.'
print(multiline) # Note: multiline is a tuple of strings (see below)
abc 12 3.14 multiline is possible, if there are braces ('a long statement may be split using backslash', 'this is still the same statement', 'the end.')
Zeichenketten (Strings)¶
Die Syntax erlaubt es drei verschiedene Möglichkeiten für Zeichenketten:
string_single_quotes = 'abc'
string_double_quotes = "abc"
string_triple_quotes = """this is
a multiline
string."""
# Note: a multiline string is a python here-document
# It's useful when we need to include quotes in a string:
string1 = 'hello "world"'
string2 = "don't"
# Otherwise we have to use backslashes:
string2 = 'don\'t'
# Other special characters: http://docs.python.org/ref/strings.html
# Strings are objects which support many operations:
strings = string1 + " : " + string2
print(strings)
# better: use join!
print(" ".join([string1, ':', string2]))
hello "world" : don't hello "world" : don't
(Objekt-orientiert) Punkt-Notation erlaubt es auf Instanzen (hier von Zeichenketten) Methoden auszurufen:
strings_uppercase = strings.upper()
strings_uppercase
'HELLO "WORLD" : DON\'T'
Weitere Zeichenketten-Methoden siehe z.B.: http://docs.python.org/lib/string-methods.html
Slicing¶
Extraktion von Substrings via Slicing:
beginning = strings[0:4]
beginning
'hell'
String Formating Syntax¶
name = "Klaus"
age = 74
# simple concatenate - note the explicit cast of the int
"Hello " + name + ". You are " + str(age) + "."
'Hello Klaus. You are 74.'
# old school %-formating
"Hello, %s. You are %i." % (name, age)
'Hello, Klaus. You are 74.'
# str.format()
"Hello, {}. You are {}.".format(name, age)
'Hello, Klaus. You are 74.'
"Hello, {1}. You are {0}.".format(age, name)
'Hello, Klaus. You are 74.'
Tipp: Verwenden Sie f-Strings:
# Note the f before the first "
f"Hello, {name}. You are {age}."
'Hello, Klaus. You are 74.'
# you can also use methods inside the f-String
f"{name.lower()} is funny."
'klaus is funny.'
Stripping¶
a_string = " lol abc lol "
print(a_string)
# Strip spaces at beginning and end of a string:
stripped = a_string.strip()
print(stripped)
lol abc lol lol abc lol
Ersetzungen¶
Ersetze eine Substring in einem String:
print(a_string)
newstring = a_string.replace('abc', 'def')
print(newstring)
lol abc lol lol def lol
Strings sind immutable¶
Strings sind Konstanten, die nicht geändert werden können. Alle String-Operationen erzeugen neue Strings.
Strings vs. Bytestrings¶
- Ein String ist eine Sequenz von Zeichen (characters), d.h. eine Zeichenkette.
- Ein Bytestring ist eine Sequenz von Bytes. Diese kann so direkt als Bitfolge bzw. Bytefolge gespeichert werden.
Die Konvertierung von Strings (Zeichenketten) zu Bytes und umgekehrt hängt von der Kodierung (dem Encoding) zusammen. In Python 3 ist der Quellcode standardmäßig in UTF-8 kodiert. Eine Tabelle der Unicode-Codeposition und der korreponierenden numerischen UTF-8 Repräsentation finden Sie z.B. in https://www.utf8-zeichentabelle.de/unicode-utf8-table.pl?number=1024. Beachten Sie, dass ein Zeichen abhängig von Zeichen mit 1-4 Bytes in UTF( repräsentiert wird.
Beispiel: Der griechische Buchstabe τ
wird in UTF-8 mit zwei Bytes kodiert (numerische Repräsentation).
- binär: 11001111 10000100
- hexadezimal: 0xcf 0x84
als
- Bytestring
b'\xcf\x84'
als zwei Hexadezimalzahlen - Als UTF-8 String
τ
(Zeichenkette mit nur einem Zeichen)
'τ'.encode('utf-8')
b'\xcf\x84'
#0xF0 0x9D 0x9C 0x8F
b'\xcf\x84'.decode('utf-8')
'τ'
Gewisse Zeichen (ein Byte-Zeichen?) werden im Bytestringdarstellung auch direkt als entsprechendes Zeichen dargestellt:
# "latin small letter o" ist 0x6f in UTF-8
# "6" is 0x36
b'\x6f\x36'
b'o6'
An folgendem Beispiel wird der Unterschied zwischen verschiedenen (Unicode)-Kodierungen klar. D.h. dieselbe Bytefolge kann abhängig von der Kodierung eine andere Stringfolge ergeben.
print(b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-16'))
print(b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-8'))
蓏콯캁澽苏 τoρνoς
Hinweis:
- Mehr zu Operationen auf Zeichenketten bzw. String-Methoden (etc.) und Unicode (Encoding und Decoding) finden Sie z.B. im NLTK-Buch Kapitel 3 (in 3.2 Strings und 3.3 Text Processing with Unicode)
- Mehr zum Unterschied zwischen Strings und Bytestrings: https://stackoverflow.com/questions/6224052/what-is-the-difference-between-a-string-and-a-byte-string
- Für den Unterschied zwischen Unicode und Implementierungen wie UTF-8, siehe z.B. https://stackoverflow.com/questions/643694/what-is-the-difference-between-utf-8-and-unicode
Listen (lists)¶
Eine Liste ist ein dynamisches Array von beliebigen Objekten/Typen:
Diese werden über eckige Klammern (square brackets) deklariert:
# declare a empty lists by
a_list = [] # or by
a_list = list()
type(a_list)
list
a_list.append(3) # append an element
a_list.append("bla")
a_list
[3, 'bla']
a_list = [1, 2, 3, 'abc', 'def']
# Lists may contain lists:
another_list = [a_list, 'abc', a_list, [1, 2, 3]]
# (in this case, "a_list" is only a pointer)
# Access a specific element by index (index starts at zero):
elem = another_list[1]
print(elem)
elem2 = another_list[3][1]
print(elem2)
abc 2
# It's easy to test if an item is in the list:
if 'abc' in a_list:
print('bingo!')
bingo!
# Extracting a part of a list is called slicing:
list2 = a_list[2:4] # Returns a list with items 2 and 3 (not 4)
print(list2)
[3, 'abc']
# Other list operations like appending:
print(a_list)
a_list.append('ghi')
print(a_list)
a_list.remove('abc')
print(a_list)
[1, 2, 3, 'abc', 'def'] [1, 2, 3, 'abc', 'def', 'ghi'] [1, 2, 3, 'def', 'ghi']
List Comprehension¶
vals = [1, 2, 3, 5, 7, 9, 10]
double_vals = [2 * v for v in vals]
print(double_vals)
[2, 4, 6, 10, 14, 18, 20]
Weitere Listen-Operationen siehe http://docs.python.org/lib/typesseq.html
Tuples¶
Ein Tuple ist ähnlich einer Liste, aber mit fester Länge (fixed-size) und unveränderlich (immutable). Die Elemente eines Tupels können nicht geändert oder gelöscht werden. Neue Elemente können nicht an- oder eingefügt werden
Die Elemente werden mittels Komma getrennt, wobei meist die Tuples mittels runden Klammern deklariert werden:
a_tuple = (1, 2, 3, 'abc', 'def')
a_tuple[3] # element indexing starts with 0
'abc'
# But parentheses are optional:
another_tuple = 1, 2, 3, 'abc', 'def'
another_tuple
(1, 2, 3, 'abc', 'def')
# Tip: a tuple containing only one item must be declared using a comma,
# else it is not considered as a tuple:
a_single_item_tuple = 'one value',
type(a_single_item_tuple)
tuple
Mehr zu Tupeln: http://docs.python.org/library/stdtypes.html#sequence-types-str-unicode-...
Dictionaries¶
(analog zu Maps in Java)
Dictionaries (dict
) sind Schlüssel-Wert Abbildungen (Key-Value Maps), analog einer mathematischen Funktion.
Dictionaries können über geschweifte Klammern deklariert werden:
point = {} # form an empty dictionary or by:
point = dict()
p = (1.2, -40.0, 29)
point['x'] = p[0]
point['y'] = p[1]
point['z'] = p[2]
point['z']
29
# declare a dict by curly brackets
point = {'x': p[0], 'y': p[1], 'z': p[2]}
point['z'] = 55.
point = {'x': p[0], 'y': p[1], 'z': p[2]}
del point['x']
# print(point['x']) # raises an error
print(point.get('x')) # returns None
None
if 'x' not in point:
print('missing x')
for key in point:
print(key)
missing x y z
Blocks und Einrückungen (Kontrollfluss - control flow)¶
Code-Blöcke werden durch Einrückungen (indentation) abgegrenzt (und nicht durch Klammern {
}
). Einrückungen entstehen durch Tabs oder Leerzeichen.
Tipp: Niemals Tabs mit Leerzeichen mischen, da dann die Tiefe der Einrückung oft nicht visuell richtig angezeigt wird. Am besten einen Editor/IDE verwenden, die Tabs in Leerzeichen konvertiert.
if / elif / else - Abzweigungen¶
a = 3
print(a)
if a == 3:
print('The value of a is:')
print('a=3')
3 The value of a is: a=3
if a == 'test':
print('The value of a is:')
print('a = "test"')
test_mode = True
else:
print('a != "test"')
test_mode = False
# do_something_else()
a != "test"
b = 2
if a == 1 or a == 2:
pass # do nothing
elif a == 3 and b > 1:
pass
elif a == 3 and not b > 1:
pass
else:
pass
while
Loops¶
a = 1
while a < 10:
print(a)
a += 1
1 2 3 4 5 6 7 8 9
for
Loops¶
Ein Python for-Schleife ist eigentlich eine foreach-Schleife:
for a in range(4):
print(a)
0 1 2 3
my_list = [2, 4, 8, 16, 32]
for a in my_list: # my_list has to be an iterator
print(a)
2 4 8 16 32
Mehr zu Kontrollfluss: http://docs.python.org/tutorial/controlflow.html
Funktionen¶
Eine Funktion wird definiert mittels des def
Schlüsselworts:
def my_function(arg1, arg2, arg3='default value'):
print('arg1 =', arg1)
print('arg2 =', arg2)
print('arg3 =', arg3)
# Call it (note that arguments are not strongly typed):
my_function(17, 'abc', "def")
my_function(17, 'abc')
arg1 = 17 arg2 = abc arg3 = def arg1 = 17 arg2 = abc arg3 = default value
Es können (zur Dokumentation) Typ-Hinweise gegeben werden:
# type hints
def my_function(arg1: int, arg2: str, arg3: str = 'default value') -> None:
print('arg1 =', arg1)
print('arg2 =', arg2)
print('arg3 =', arg3)
# The 3rd arg may be omitted:
my_function('a string', 12)
arg1 = a string arg2 = 12 arg3 = default value
# A function may return a value:
def fun2():
print('fun2')
return 'any return value'
# call it:
print('fun2() = %s' % fun2())
fun2 fun2() = any return value
Funktionale Aspekte von Python¶
Funktionen sind Bürger erster Klasse (first-class citizen). Funktionen können in Variablen gespeichert werden und als Funktionsargumente übergeben werden.
def f(x):
return x ** 2
def operate(h, x): # higher-order function
print(h(x))
operate(f, 5)
25
Anonyme Funktionen (lambda functions)¶
Mittels des lambda
-Schlüsselworts können anonyme Funktionen erzeugt werden:
g = lambda x: x**3 # assign to the variable g the unnamed function
g(5)
# Note: this is not pep8 conform.
125
operate(lambda x: x**3, 5)
125
def make_incrementor(n):
return lambda x: x + n
f = make_incrementor(n=3)
f(2)
5
g = make_incrementor(7)
g(5)
12
print(make_incrementor(n=7)(x=8))
print(make_incrementor(7)(8))
15 15
foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]
# map and filter return iterators in python3
print(list(filter(lambda x: x % 3 == 0, foo)))
print(list(map(lambda x: x * 2 + 10, foo)))
[18, 9, 24, 12, 27] [14, 46, 28, 54, 44, 58, 26, 34, 64]
from functools import reduce
print(reduce(lambda x, y: x + y, foo))
print(sum(foo))
print(reduce(lambda x, y: x + y, map(lambda x: x * 2 + 10, foo)))
139 139 368
from operator import add
reduce(add, map(lambda x: x * 2 + 10, foo))
368
import operator
expr = "28+32+++32++39"
print(reduce(add, map(int, filter(bool, expr.split("+") ))))
operator.mul(3, 10)
operator.pow(2, 3)
operator.itemgetter(1)([1, 2, 3])
# more see http://ua.pycon.org/static/talks/kachayev
131
2
print("expr is of type: ",type(expr))
# split expr on the separator '+'
print(expr.split("+"))
expr.split("+")
# filter with "bool" as operator
print(list(filter(bool, expr.split("+") )))
print(list(map(bool, expr.split("+") )))
# all empty strings are False, not empty strings are True
# cast the string-list elements to int
# with "int" as operator
list(map(int, filter(bool, expr.split("+"))))
# add up all elemets with add-operator
print(reduce(add, map(int, filter(bool, expr.split("+") ))))
expr is of type: <class 'str'> ['28', '32', '', '', '32', '', '39'] ['28', '32', '32', '39'] [True, True, False, False, True, False, True] 131
Kommandozeilen-Argumente¶
Um Argumente auf der Kommandozeile einem Skript zu übergeben, ist es notwendig Module von der Standard Library zu importieren:
import sys
print(f"Name of the script : {sys.argv[0]=}")
print(f"Arguments of the script : {sys.argv[1:]=}")
Tipp: Verwenden Sie lieber das argparse
-Modul, um Kommandozeilenargumente
zu behandeln. Arbeiten Sie hierzu das argparse
-Tutorial durch.
mehr zu Kommandozeilenargumenten siehe https://realpython.com/python-command-line-arguments/
Dateiverarbeitung¶
Öffnen einer Datei zum Lesen:
f = open('my_file.txt')
# open() returns a file object with several methods.
# To read a specific number of characters:
s = f.read(10)
# To read the whole file in a string
s = f.read()
#To close an open file:
f.close()
To iterate over file lines:
f = open('my_file.txt')
for line in f:
print (line)
f.close()
Besser mit with
-Statement (Context Manager) - auch zur Fehlerbehandlung (siehe unten):
# open for read 'r'
with open('../bash/work/countries.txt', 'r') as f:
for line in f:
print(line, end='') # there is already a newline at the end
France Canada Burkina Faso Democratic Republic of the Congo Russia New Zealand
Öffnen von Dateien zum Schreiben (write w
) auch am besten mit with
-Statement:
with open('out_file.txt', 'w') as fw:
fw.write('a line of text\n') # note '\n' is necessary here
fw.write(a_string)
Für weitere Datei-Operationen siehe z.B. http://docs.python.org/lib/bltin-file-objects.html
OS Modul¶
Um mit Dateien umzugehen, z.B. um eine Datei zu löschen werden wieder Module aus der Standard Bibliothek benötigt:
import os, os.path
if os.path.exists('my_file.txt'):
os.remove('my_file.txt')
import os
Laufendes Arbeitsverzeichnis¶
cwd = os.getcwd()
type(cwd)
str
Wechseln des Arbeitsverzeichnis¶
os.chdir(path)
Verzeichnisinhalt auflisten¶
Anzeigen der Dateien für eine Verzeichnis: os.listdir(".")
(hier übergeordnetes Verzeichnis des Arbeitverzeichnis)
files = os.listdir("..")
type(files), type(files[0]) # python list of str
(list, str)
Erzeugen eines Verzeichnisses¶
os.mkdir(name_of_dir)
Umgebungsvariablen¶
z.B. HOME
Umgebungsvariable erhalten:
os.environ['HOME']
'/home/christian'
Unix/Linux User/Group Funktionalitäten¶
z.B: User-Id erhalten:
os.getuid()
1000
Information zum Betriebssystem¶
os.uname()
posix.uname_result(sysname='Linux', nodename='wittgenstein', release='6.2.0-36-generic', version='#37~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Oct 9 15:34:04 UTC 2', machine='x86_64')
Ausführen eines Programms in einer Subshell¶
os.system(some_command)
Dies ist nicht zu empfehlen. Verwenden Sie stattdessen das Modul subprocess
(siehe unten).
für mehr zum OS-Modules siehe
help(os)
oder die Referenz https://docs.python.org/3.9/library/os.html
Module subprocess¶
Einfaches Ausführen eines Kommandos in einem Unterprozess subprocess.run(command)
import subprocess
proc = subprocess.run(["ls", "-l"],
universal_newlines=True,
stdout = subprocess.PIPE)
proc_out = proc.stdout.splitlines()
print(proc_out)
['total 196', '-rw-rw-r-- 1 christian christian 69094 Dez 16 2021 extract_ard_politik_talkshows.ipynb', '-rw-rw-r-- 1 christian christian 0 Mai 6 2021 geckodriver.log', '-rw-rw-r-- 1 christian christian 13310 Jan 11 2022 Idiomatic_python.ipynb', 'drwxrwxr-x 4 christian christian 4096 Jan 25 2022 intro_exercises', '-rw-rw-r-- 1 christian christian 116 Mär 10 2021 literatur.txt', '-rw-rw-r-- 1 christian christian 3796 Dez 21 2021 minesweeper.py', '-rw-rw-r-- 1 christian christian 659 Nov 17 14:58 mymodule.py', 'drwxrwxr-x 4 christian christian 4096 Nov 17 15:01 programs', 'drwxrwxr-x 2 christian christian 4096 Nov 17 14:58 __pycache__', '-rw-rw-r-- 1 christian christian 77216 Nov 17 15:03 Python-Grundlagen.ipynb', '-rw-rw-r-- 1 christian christian 2260 Mai 7 2021 Python-os-Modul.ipynb', '-rw-rw-r-- 1 christian christian 2173 Mai 7 2021 selenium.ipynb', '-rw-rw-r-- 1 christian christian 0 Nov 7 2021 stderr.txt', '-rw-rw-r-- 1 christian christian 201 Jan 31 2021 test.py']
Auch Pipes etc. möglich.
Mehr siehe https://docs.python.org/3/library/subprocess.html
Klassen¶
Python erlaubt Klassen-basierte objektoriente Programmierung.
Eine Klasse gibt die Struktur für Instanzen der Klassen (Objekte) vor. Operationen auf den Instanzen können mittels Methoden ("Funktionen" für Klassen) definiert werden.
In Python enthält eine Klasse also
- Attribute (attributes), d.h. Variablen und
- Methoden (methods).
Eine Klasse wird mit dem class
-Schlüsselwort definiert.
Jeder Methode der Klasse sollte als erstes Argument
self
haben (Referenz auf die laufende Instanz der Klasse).Einige Methoden haben spezielle Bedeutung, z.B.:
__init__
: Konstruktor zum Ereugen einer Instanz.__str__
: Methode, die eine String-Repräsentation der Klasse beinhaltet.- für weitere siehe http://docs.python.org/3/reference/datamodel.html#special-method-names
class Point:
"""
Simple class for representing a point in a Cartesian coordinate system.
"""
def __init__(self, x, y):
"""
Create a new Point at x, y.
"""
self.x = x # instance variable self.x
self.y = y
def translate(self, dx, dy):
"""
Translate the point by dx and dy in the x and y direction.
"""
self.x += dx
self.y += dy
def __str__(self):
return("Point at [%f, %f]" % (self.x, self.y))
def __add__(self, other):
return Point(self.x + other.x, self.x + other.x)
# To create a new instance of a class:
p1 = Point(1, 2) # this will invoke the __init__ method in the Point class
print(p1) # this will invoke the __str__ method
Point at [1.000000, 2.000000]
p1 = Point(2, 3)
p3 = p1 + p1
print(p3)
Point at [4.000000, 4.000000]
# To invoke a class method in the class instance `p`:
p2 = Point(1, 1)
# this modifies the internal store coordinates
p1.translate(0.25, 1.5)
print(p1)
print(p2)
Point at [2.250000, 4.500000] Point at [1.000000, 1.000000]
Methoden können dynamisch zu Klassen hinzugefügt werden:
def point_add(self, other):
"""
Defines the +-Operator
"""
assert isinstance(other, Point) # check the type
newPoint = Point(self.x, self.y)
newPoint.x += other.x
newPoint.y += other.y
return newPoint
# __add__ is the special methods for implementing the +-Operator
# we can dynamically extend the class Point by this method
Point.__add__ = point_add
print(p1 + p2)
Point at [3.250000, 5.500000]
Exceptions¶
Wenn zur Laufzeit Bedingungen, die erfüllt sein müssten, nicht gegeben sind, können Exceptions (Ausnahmen) geworfen werden. Wenn beispielsweise die mathematische Operation Teile $a$ durch $b$ ausgeführt werden soll, macht dies nur Sinn mit der Bedingung, dass $b\neq 0$ ist. Hier kann in der Implementierung der Teil-Opration dies überprüft werden und falls dies nicht der Fall ist eine Exception geworfen werden.
In Python werden Exceptions mittels raise
geworfen:
raise Exception("description of the error")
--------------------------------------------------------------------------- Exception Traceback (most recent call last) Cell In[90], line 1 ----> 1 raise Exception("description of the error") Exception: description of the error
# A typical use of exceptions is to abort functions
# when some error condition occurs, for example:
def point_add2(self, other):
"""
Defines the +-Operator
"""
if not isinstance(other, Point): # check the type
raise TypeError("Second argument of +-Operator is not a Point!")
newPoint = Point(self.x, self.y)
newPoint.x += other.x
newPoint.y += other.y
return newPoint
Point.__add__ = point_add2
p3 = Point(2., 3.)
print(p3 + 4.) # this causes an exception
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[92], line 2 1 p3 = Point(2., 3.) ----> 2 print(p3 + 4.) # this causes an exception Cell In[91], line 8, in point_add2(self, other) 4 """ 5 Defines the +-Operator 6 """ 7 if not isinstance(other, Point): # check the type ----> 8 raise TypeError("Second argument of +-Operator is not a Point!") 9 newPoint = Point(self.x, self.y) 10 newPoint.x += other.x TypeError: Second argument of +-Operator is not a Point!
Fangen von Exceptions¶
Programmcode sollte mit Exceptions (Ausnahmen) umgehen können. Dazu sollte in der Beschreibung der Schnittstellen zu Modulen (siehe unten) angegeben sein, welche Ausnahmen auftreten können. Das Behandeln von Ausnahmen wird als Exception Handling bezeichnet.
Dabei werden in Python mittels try
und except
die Ausnahmen/Fehler "gefangen", um damit programmatisch umzugehen:
import sys
try:
print("test if we can add an int:")
p4 = p3 + 4
except Exception as e:
print("Caught an exception: ", str(e), file=sys.stderr) # print to stderr
#
test if we can add an int:
Caught an exception: Second argument of +-Operator is not a Point!
Beachte: Einfaches Ausgeben der Exception-Ursache und Weiterausführen des Codes (wie im obigen Beispiel) ist ein Antipattern. Dies kann zu schwer zu findenden Bugs führen, da in der Regel, die Exception nicht ohne Grund geworfen wurde. Richtiges Exception-Handling ist bei der Softwareentwicklung sehr wichtig.
Mehr zum Thema Fehler und Exceptions, siehe z.B. https://docs.python.org/3/tutorial/errors.html
Module¶
Leden Sie den Anfang von https://docs.python.org/3.9/tutorial/modules.html
Module¶
Eines der wichtigsten Konzepte guter Programmierung ist die Wiederverwendung von Code und die Vermeidung von Wiederholungen.
Funktionen und Klassen sollten mit einem klar definierten Zweck und Umfang geschrieben und wiederverwendet werden. D.h. sie sollten nicht ähnlichen Code in verschiedenen Teilen eines Programms wiederholen.
So wird die Lesbarkeit und Wartbarkeit eines Programms erheblich verbessert. In der Praxis bedeutet dies, dass Programme weniger Fehler aufweisen, leichter zu erweitern und zu debuggen sind und Fehler leichter zu beheben sind.
Python unterstützt die modulare Programmierung auf verschiedenen Ebenen. Funktionen und Klassen sind Beispiele für Werkzeuge zur modularen Programmierung auf niedriger Ebene. Python-Module sind ein modulares Programmierkonstrukt auf höherer Ebene, bei dem wir zusammengehörige Variablen, Funktionen und Klassen in einem Modul zusammenfassen können. Ein Python-Modul wird in einer Python-Datei (mit der Dateiendung .py
) definiert und kann mit der Anweisung import
anderen Python-Modulen und -Programmen zugänglich gemacht werden.
Betrachten wir das folgende Beispiel: Die Datei mymodule.py
enthält einfache Beispielimplementierungen einer Variablen, einer Funktion und einer Klasse:
%%file mymodule.py
# ipython magic function writes the content of the cell to a text file "mymodule.py"
"""
Example of a python module. Contains a variable called my_variable,
a function called my_function, and a class called MyClass.
"""
my_variable = "Hello World"
def my_function():
"""
Example function
"""
return my_variable
class MyClass:
"""
Example Overwriting mymodule.pyclass.
"""
def __init__(self):
self.variable = my_variable
def set_variable(self, new_value):
"""
Set self.variable to a new value
"""
self.variable = new_value
def get_variable(self):
return self.variable
Overwriting mymodule.py
# We can import the module `mymodule` into our Python program using `import`:
import mymodule
# Use `help(module)` to get a summary of what the module provides:
# automatically generated from the comments
help(mymodule)
Help on module mymodule: NAME mymodule DESCRIPTION Example of a python module. Contains a variable called my_variable, a function called my_function, and a class called MyClass. CLASSES builtins.object MyClass class MyClass(builtins.object) | Example class. | | Methods defined here: | | __init__(self) | Initialize self. See help(type(self)) for accurate signature. | | get_variable(self) | | set_variable(self, new_value) | Set self.variable to a new value | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) FUNCTIONS my_function() Example function DATA my_variable = 'Hello World' FILE /home/christian/nextcloud/HTW/Lehre/praktischeInformatik/python/mymodule.py
mymodule.my_variable
'Hello World'
mymodule.my_function()
'Hello World'
my_class = mymodule.MyClass()
my_class.set_variable(10)
my_class.get_variable()
10
Übung Recherche¶
Recherchieren Sie weshalb Python-Dateien oft die Konstruktion if __name_ == "__main__"
enthalten. Wie funktioniert die Konstruktion? Was ist der Sinn der Konstruktion, bzw. wann wird diese eingesetzt?
Referenzen¶
(freie) Online-Lehrbücher¶
- Jake VanderPlas: A Whirlwind Tour of Python
- Allen B. Downey: Think Python (2nd edition) - A free book on Python programming (2nd edition).
Tutorials¶
- J.R. Johansson: Scientific Python Lectures: Introduction to Python programming - Lecture 1
Weitere Quellen¶
- http://www.python.org - The official web page of the Python programming language.
- http://www.python.org/dev/peps/pep-0008 - Style guide for Python programming. Highly recommended.
- Python Essential Reference - A good reference book on Python programming.