Intermezzo Coding Style PEP8 Coding Style PEP8 Was ist ein Coding Style Layout Imports Einrückung und Zeilenlänge Runde Klammern Leerzeilen Leerzeichen Namensregeln pep8.py PRG, SS 13 May 27, 2013 1
Coding Style PEP8 Was ist ein Coding Style Jetzt können wir schon ein wenig programmieren. Aber jeder schreibt seine Programme ein wenig anders. Auch wenn man sich an die Syntax-Regeln halten muss. Das ist ungeschickt, wenn man gemeinsam programmiert. Man sollte ein gewisses Format oder einen Stil einhalten: Coding Style. Erleichtert das Lesen und das Verstehen des Codes. Auch für einen selber. Betrifft Layout, Einrückungen, Leerzeilen, Leerzeichen, Klammerung,... Schauen auf Style Guide for Python Code (PEP8) http://www.python.org/dev/peps/pep-0008/ Google Python Style Guide, http://google-styleguide.googlecode.com/svn/trunk/pyguide.html was man selber gut findet Coding Style PEP8 Layout Grobe Aufteilung der Programm-Strukturen 1. Alle Import-Statements, 2. Alle Konstanten und globalen Variablen, 3. Alle Funktionen, alle Klassen, 4. Main-Funktion. Dazu kommen natürlich Kommentare im Code und Dokumentationen des Moduls, der Funktionen und der Klassen. PRG, SS 13 May 27, 2013 2
Coding Style PEP8 Layout #----------------------------------------------------------- # begin of file *foo.py* # module imports # contant defs # class defs # function defs # main fcn if name == " main ": main() # end of file *foo.py* #----------------------------------------------------------- Coding Style PEP8 Imports Jeder Modul-Import soll auf eine eigene Zeile. import os import sys import os, sys Von einem Modul darf aber vieles importiert werden. from math import sin, cos, pi Sortieren bei vielen Imports nach: 1. Standard-Module, 2. Externe-Module, 3. eigene Module. Und dann alphabetisch. PRG, SS 13 May 27, 2013 3
Coding Style PEP8 Einrückung und Zeilenlänge Einrückung immer mit 4 Leerzeichen. Niemals Leerzeichen und Tabs mischen. Python-Editoren (IDLE, Spyder) ersetzen Tabs durch Leerzeichen. for x in range(255): for y in range(255): img[x,y] = x*y for x in range(255): for y in range(255): img[x,y] = x*y Coding Style PEP8 Einrückung und Zeilenlänge Maximale Zeilenlänge ist 80 Zeichen. Lange Zeilen geschickt umbrechen mit Einrückungen. Ausnahmen: lange Import-Statements, lange URLs in Kommentaren. # Aligned with opening delimiter foo = long_function_name(var_one, var_two, var_three, var_four) # More indentation included to distinguish this from the rest. def long_function_name( var_one, var_two, var_three, var_four): print(var_one) # Arguments on first line forbidden when not using vertical alignment foo = long_function_name(var_one, var_two, var_three, var_four) # Further indentation required as indentation is not distinguishable def long_function_name( var_one, var_two, var_three, var_four): print(var_one) PRG, SS 13 May 27, 2013 4
Coding Style PEP8 Einrückung und Zeilenlänge Zeilenumbruch zwischen Klammern: (), {}, []. foo_bar(self, width, height, color= black, design=none, x= foo, emphasis=none, highlight=0) if (width == 0 and height == 0 and color == red and emphasis == strong ): my_list = [ 1, 2, 3, 4, 5, 6, ] result = some_function_that_takes_arguments( a, b, c, d, e, f, ) Coding Style PEP8 Einrückung und Zeilenlänge Auch lange Strings umbrechen. x = This will build a very long long long long long long long long string x = ( This will build a very long long long long long long long long string ) PRG, SS 13 May 27, 2013 5
Coding Style PEP8 Runde Klammern Man verwende nicht zuviele runde Klammern (). if (foo): bar() if not(x): bar() if ((x) and (y)): bar() while (x): x = bar() return (foo) if foo: bar() while x: x = bar() if x and y: bar() if not x: bar() return foo Coding Style PEP8 Leerzeilen Man sollte Leerzeilen verwenden, um Struktur herauszustellen. Zwei Leerzeilen zwischen Funktionsdefinitionen. Weitere Leerzeilen zwischen Funktionsgruppen. Und wann immer man meint, dass es sinnvoll ist und die Lesbarkeit erhöht. PRG, SS 13 May 27, 2013 6
Coding Style PEP8 Leerzeichen Keine Leerzeichen innerhalb von Klammern. spam( ham[ 1 ], { eggs: 2 }, [ ] ) spam(ham[1], {eggs: 2}, []) Keine Leerzeichen vor Kommata, Simokola oder Doppelpunkten. if x == 4 : print x, y x, y = y, x if x == 4: print x, y x, y = y, x Coding Style PEP8 Leerzeichen Keine Leerzeichen vor Klammern, die zu einer Argumentliste, einem Index oder einem Slice gehören. spam (1) spam(1) dict [ key ] = list [index] dict[ key ] = list[index] PRG, SS 13 May 27, 2013 7
Coding Style PEP8 Leerzeichen Verwende ein Leerzeichen vor und nach folgenden binären Operatoren: =, +=, -=,..., ==, <,..., and, or,... Verwende Leerzeichen bei den Rechenoperatoren nach Priorität. i=i+1 submitted +=1 x = x * 2-1 hypot2 = x * x + y * y c = (a + b) * (a - b) i = i + 1 submitted += 1 x = x*2-1 hypot2 = x*x + y*y c = (a+b) * (a-b) Coding Style PEP8 Leerzeichen Verwende keine Leerzeichen, um Zuweisungen anzupassen. x = 1 y = 2 long_variable = 3 x = 1 y = 2 long_variable = 3 Verwende keine Leerzeichen, bei Zuweisungen von Default-Werten. def complex(real, imag = 0.0): return magic(r = real, i = imag) def complex(real, imag=0.0): return magic(r=real, i=imag) PRG, SS 13 May 27, 2013 8
Coding Style PEP8 Namensregeln Verschiedene Konventionen für Namen vorhanden: b, einzelner Kleinbuchstabe B, einzelner Großbuchstabe lowercase, alles in Kleinbuchstaben lower_case_with_underscores, Kleinbuchstaben mit Unterstrich UPPERCASE, alles in Großbuchstaben UPPER_CASE_WITH_UNDERSCORES, Großbuchstaben mit Unterstrich CapitalizedWords, CamelCase mixedcase Vermeide die Namen l, O und I. Vermeide eigene Namen mit vorderen und hinteren doppelten Unterstrichen: nicht erfinden Coding Style PEP8 Namensregeln Namensgebung konsistent für den Code durchhalten. Google schlägt vor Typ Modul Klasse Exception Funktionen Konstante Variablen Name lower_with_under CapWords CapWords lower_with_under() CAPS_WITH_UNDER lower_with_under PRG, SS 13 May 27, 2013 9
Coding Style PEP8 pep8.py Man kann seinen Code auf obigen Code-Style prüfen. Dazu easy_install pep8 und dann C:> pep8 --show-pep8 --first meinedatei.py Und mehr Hilfe über C:> pep8 --help Module Externe Module PRG, SS 13 May 27, 2013 10
Mathematik: math, cmath Datenbank: sqlite3 Weitere interessante Python kommt mit batteries included. Das soll bedeuten, dass Python schon jede Menge Funktionalität mitbringt und dadurch die Entwicklung von Programmen unterstützt. Diese Funktionalität wird in Modulen zur Verfügung gestellt, die dann importiert werden können. Wir werden hier einige der Standard-Module kurz (also nicht vollständig) und ohne spezielle Reihenfolge vorstellen. liegen jedem Python bei, unabhängig von der Distribution. Das Modul random erzeugt Pseudo-Zufallszahlen. Der Zufall wird auf dem Rechner algorithmisch realisiert, ist also eigentlich nicht wirklich zufällig. Und deshalb nur pseudo - zufällig. In dem Modul random gibt es zum einen Funktionen, die mit dem Zufall umgehen, als auch eine Klasse, die für den Zufall zuständig ist. Wir betrachten hier nur die Funktionen. Wir setzen im folgenden voraus, dass das Modul schon importiert wurde: import random PRG, SS 13 May 27, 2013 11
Einen ersten Eindruck (muss man nicht alles kennen) von dem Inhalt liefert >>> dir(random) [ BPF, LOG4, NV_MAGICCONST, Random, SG_MAGICCONST, TWOPI, WichmannHill, _BuiltinMethodType, all, builtins, doc, file, name, _acos, _cos, _e, _exp, _floor, _inst, _log, _pi, _random, _sin, _sqrt, _test, _test_generator, betavariate, choice, cunifvariate, expovariate, gammavariate, gauss, getstate, jumpahead, lognormvariate, normalvariate, paretovariate, randint, random, randrange, sample, seed, setstate, shuffle, stdgamma, uniform, vonmisesvariate, weibullvariate ] Name choice(seq) gauss(mu,sigma) random() randrange([start],stop,[step]) seed(x) shuffle(list) uniform(a,b) Bedeutung Zufällige Auswahl eines Elementes aus einer Sequenz Liefert eine relle Zufallszahl bzgl. der Gauss-Verteilung mit Mittelwert mu und Standardabweichung sigma Liefert eine relle Zufallszahl bzgl. der Gleichverteilung aus [0, 1) Zufällige Auswahl aus range(start,stop,step) Initialisiert den Zufallsgenerator mit Integer x Mischt die Liste list Liefert eine relle Zufallszahl bzgl. der Gleichverteilung aus [a, b) PRG, SS 13 May 27, 2013 12
Wir erzeugen zuerst reelle Zufallszahlen. Dazu gibt es verschiedene Methoden, etwa >>> for i in range(3): print random.random() 0.149271001451 0.911341090764 0.485720954008 erzeugt gleichverteilte Zufallszahlen im Intervall [0, 1). Und >>> for i in range(3): print random.uniform(-3.14,3.14) 2.77418761413 1.36563618462-2.59583464853 erzeugt gleichverteilte Zufallszahlen im Intervall [ π, π). Und >>> for i in range(3): print random.gauss(42.0,4.0) 46.4030253422 43.669799878 40.8402909232 erzeugt normalverteilte Zufallszahlen um µ = 42 mit σ = 4. Hier dazu noch einen grafischen Eindruck: >>> N = 2**14 >>> x = [random.random() for i in range(n)] >>> y = [random.uniform(-3.14,3.14) for i in range(n)] >>> z = [random.gauss(42.0,4.0) for i in range(n)] >>> from pylab import hist, show >>> hist(x,bins=25) >>> hist(y,bins=25) >>> hist(z,bins=25) >>> show() random() uniform(-3.14,3.14) gauss(42.0,4.0) PRG, SS 13 May 27, 2013 13
Neben dem generieren von Zufallszahlen kann das Modul auch mit Sequenzen umgehen. Etwa >>> l = [ a, b, c, d, e ] >>> for i in range(10): print random.choice(l), b d c c c e a b d c Wählt zufällig aus einer gegebenen Liste ein Element aus. Oder aus einer Zahlenliste >>> for i in range(10): print random.randrange(42,48), 43 42 43 44 47 44 45 44 42 46 Ausserdem kann man eine Liste auch vollständig durchmischen ( in-place ). >>> print l [ a, b, c, d, e ] >>> random.shuffle(l) >>> print l [ c, b, a, d, e ] In die richtige Reihenfolge bekommt man es dann wieder mit >>> l.sort() >>> print l [ a, b, c, d, e ] Das ganze sieht doch sehr zufällig aus! Das es dennoch algorithmisch ist, zeigt folgender Programmkode: >>> random.seed(815) >>> for i in range(10): print random.choice(l), e b d b a c d d b d >>> for i in range(10): print random.choice(l), c a b a e c a a d e >>> random.seed(815) >>> for i in range(10): print random.choice(l), e b d b a c d d b d Mit der Funktion seed wird der Zufallsgenerator initialisiert. Wiederholt man die Initialsierung, wiederholt sich auch der Zufall! Üblicherweise wird beim Start von Python der Zufallsgenerator mit der aktuellen Zeit initialisiert. PRG, SS 13 May 27, 2013 14
Und wofür braucht man den Zufall in der Programmierung? Nun,beispielsweise bei Spielen, in denen der Computer Würfeln soll: >>> for i in range(10): print random.randrange(6)+1, 4 1 5 2 5 6 3 6 1 3 Oder beim Mischen und Austeilen von Karten in einem Skatspiel: >>> farben = [ karo, herz, piek, kreuz ] >>> zahlen = [ 7, 8, 9, 10, B, D, K, AS ] >>> karten = [] >>> for f in farben: for z in zahlen: karten.append((f,z)) >>> print karten [( karo, 7 ), ( karo, 8 ), ( karo, 9 ), ( karo, 10 ), ( karo, B ), ( karo, D ), ( karo, K ), ( karo, AS ), ( herz, 7 ), ( herz, 8 ), ( herz, 9 ), ( herz, 10 ), ( herz, B ), ( herz, D ), ( herz, K ), ( herz, AS ), ( piek, 7 ), ( piek, 8 ), ( piek, 9 ), ( piek, 10 ), ( piek, B ), ( piek, D ), ( piek, K ), ( piek, AS ), ( kreuz, 7 ), ( kreuz, 8 ), ( kreuz, 9 ), ( kreuz, 10 ), ( kreuz, B ), ( kreuz, D ), ( kreuz, K ), ( kreuz, AS )] >>> random.shuffle(karten) >>> print karten [( karo, B ), ( piek, B ), ( herz, AS ), ( piek, 10 ), ( piek, 8 ), ( herz, D ), ( kreuz, 9 ), ( karo, D ), ( kreuz, AS ), ( piek, 7 ), ( kreuz, D ), ( piek, AS ), ( kreuz, K ), ( herz, 8 ), ( kreuz, 8 ), ( kreuz, 7 ), ( kreuz, 10 ), ( piek, 9 ), ( karo, AS ), ( piek, D ), ( herz, 7 ), ( herz, B ), ( karo, 7 ), ( kreuz, B ), ( piek, K ), ( karo, K ), ( herz, 9 ), ( karo, 9 ), ( karo, 10 ), ( herz, 10 ), ( karo, 8 ), ( herz, K )] >>> s1,s2,s3 = [], [], [] >>> for i in range(0,len(karten)-2,3): s1.append(karten[i]) s2.append(karten[i+1]) s3.append(karten[i+2]) >>> stich=karten[-2:] PRG, SS 13 May 27, 2013 15
>>> print s1 [( karo, B ), ( piek, 10 ), ( kreuz, 9 ), ( piek, 7 ), ( kreuz, K ), ( kreuz, 7 ), ( karo, AS ), ( herz, B ), ( piek, K ), ( karo, 9 )] >>> print s2 [( piek, B ), ( piek, 8 ), ( karo, D ), ( kreuz, D ), ( herz, 8 ), ( kreuz, 10 ), ( piek, D ), ( karo, 7 ), ( karo, K ), ( karo, 10 )] >>> print s3 [( herz, AS ), ( herz, D ), ( kreuz, AS ), ( piek, AS ), ( kreuz, 8 ), ( piek, 9 ), ( herz, 7 ), ( kreuz, B ), ( herz, 9 ), ( herz, 10 )] >>> print stich [( karo, 8 ), ( herz, K )] Man kann Signale damit verrauschen: >>> from pylab import plot, show >>> dt = 2*3.1415/512 >>> t, x = [], [] >>> for i in range(512): t.append(i*dt) x.append(math.sin(i*dt)) >>> y = x[:] >>> for i in range(512): y[i] += random.gauss(0,1) >>> plot(t,y, r,t,x, b ) >>> show() PRG, SS 13 May 27, 2013 16
Mathematik: math, cmath Die Module hatten wir schon mal. Alle üblichen reellen mathematischen Funktionen findet man in dem Modul math, alle üblichen komplexen Funktionen in cmath. >>> import math >>> dir(math) [ doc, name, package, acos, acosh, asin, asinh, atan, atan2, atanh, ceil, copysign, cos, cosh, degrees, e, erf, erfc, exp, expm1, fabs, factorial, floor, fmod, frexp, fsum, gamma, hypot, isinf, isnan, ldexp, lgamma, log, log10, log1p, modf, pi, pow, radians, sin, sinh, sqrt, tan, tanh, trunc ] >>> import cmath >>> dir(cmath) [ doc, name, package, acos, acosh, asin, asinh, atan, atanh, cos, cosh, e, exp, isinf, isnan, log, log10, phase, pi, polar, rect, sin, sinh, sqrt, tan, tanh ] Datenbank: sqlite3 In der heutigen Welt sind Datenbanken nicht mehr wegzudenken. Zumeist sind wirklich viele Daten zu verwalten, wofür man relationale Datenbanken und die Datenbanksprache SQL benötigt. Python unterstützt dies auf vielfache Weise, etwa durch Schnittstellen zu den bekanntesten Datenbanken: Oracle, Access, MySQL, PostgreSQL, SQLite,... Wir verbinden uns mit SQLite. Und sprechen in SQL (Structured Query Languag). PRG, SS 13 May 27, 2013 17
Datenbank: sqlite3 Wir wollen unsere Bücher in einer Datenbank erfassen. Dazu sollen die folgenden Informationen zu jedem Buch abgelegt werden: Autor(en): wer hat es geschrieben, VARCHAR Titel: wie heisst es, VARCHAR Genre: was für eine Geschichte ist es, VARCHAR hr: wann ist es erschienen, INTEGER Kommentar: wie find ich es, VARCHAR Das SQL-Kommando, um die zugehörige Tabelle zu erzeugen, lautet CREATE TABLE books (autor VARCHAR, titel VARCHAR, genre VARCHAR, jahr INTEGER, kommentar VARCHAR) Autor Titel Genre hr Kommenar Dan Simmons Illium SciFi 2002 ganz gut Dan Brown Illuminatus Thriller 2003 ganz schön spannend Frank Herbert Wüstenplanet SciFi 1980 Klassiker Alex Martelli Python in a Nutshell Sach 2003 recht gut Mickey Spillane Die Töchter der Nacht Krimi 1987 Klassiker Datenbank: sqlite3 Wir gehen im weiteren stets davon aus, dass wir über import sqlite3 die API zur SQLite-Datenbank importiert haben. Zuerst stellen wir eine Verbindung zur Datenbank her und erzeugen eine neuen Datenbankdatei mybooks.db im aktuellen Verzeichnis. >>> connection = sqlite3.connect("mybooks.db") Als nächstes bauen wir eine Tabelle entsprechend der Struktur unserer Daten und analog zu dem obigen SQL Kommando. >>> cursor = connection.cursor() >>> sql = """CREATE TABLE books (autor VARCHAR, titel VARCHAR, genre VARCHAR, jahr INTEGER, kommentar VARCHAR)""" >>> cursor.execute(sql) PRG, SS 13 May 27, 2013 18
Datenbank: sqlite3 Jetzt müssen wir die Tabelle noch mit Werten füllen. In SQL geht das mit INSERT INTO books(autor,titel,genre,jahr,kommentar) VALUES ( Dan Brown, Sakrileg, Thriller,2004, maechtig spannend ) Und genauso machen wir das auch in Python. >>> sql = "INSERT INTO books VALUES (?,?,?,?,?)" >>> book = ( Dan Brown, Sakrileg, Thriller,2004, maechtig spannend ) >>> cursor.execute(sql, book) >>> book = ( Dan Simmons, Illium, SciFi,2002, ganz gut ) >>> cursor.execute(sql, book) >>> connection.commit() Mit commit werden alle Daten dann auch tatsächlich über die Verbindung in die Datei eingetragen. Machen wir nun Schluss mit der Datenbank und gehen nach Hause... >>> connection.close() Datenbank: sqlite3 Beim nächsten mal können wir uns direkt mit der neuen Datenbank verbinden >>> import sqlite3 >>> connection = sqlite3.connect("mybooks.db") >>> cursor = connection.cursor() Und noch ein weiteres neues Buch dazutragen >>> sql = "INSERT INTO books VALUES (?,?,?,?,?)" >>> book = ( Frank Herbert, Der Wuestenplanet, SciFi,1980, Klassiker ) >>> cursor.execute(sql, book) Mal sehn, was schon alles darin steht. Sowas geht mit dem SELECT Befehl. SELECT * FROM books PRG, SS 13 May 27, 2013 19
Datenbank: sqlite3 Probieren wir es aus: >>> sql = "SELECT * FROM books" >>> cursor.execute(sql) >>> for book in cursor.fetchall(): print book (u Dan Brown, u Thriller, u maechtig spannend, u Sakrileg, 2004) (u Dan Simmons, u SciFi, u ganz gut, u Illium, 2002) (u Frank Herbert, u SciFi, u Klassiker, u Der Wuestenplanet, 1980) Wir bekommen die Daten als Tupel zurück. Die Tabellenspalten sind ein wenig anders angeordnet als in der Definition! Die Bedeutung der Einträge erhalten wir über >>> spalten = cursor.description >>> print spalten (( autor, None, None, None, None, None, None), ( genre, None, None, None, None, None, None), ( kommentar, None, None, None, None, None, None), ( titel, None, None, None, None, None, None), ( jahr, None, None, None, None, None, None)) >>> for desc in spalten: print desc[0], autor genre kommentar titel jahr Datenbank: sqlite3 Will man von vornherein eine gewisse Spaltenreihenfolge oder nur bestimmte Spalten, so muss man das dem SELECT Befehl mitgeben >>> sql = "SELECT autor,titel,jahr FROM books" >>> cursor.execute(sql) >>> for book in cursor.fetchall(): print book (u Dan Brown, u Sakrileg, 2004) (u Dan Simmons, u Illium, 2002) (u Frank Herbert, u Der Wuestenplanet, 1980) Und das soll es dann sein zu Python und SQLite. >>> connection.close() sqlite3 unterstützt nahezu vollständig die SQL Syntax. PRG, SS 13 May 27, 2013 20
Weitere interessante, die man sich noch anschauen könnte: os, Zugriff auf das Betriebssystem optparse, Abfrage der Kommandozeile sys, Python Systeminformationen time, Zeitfuktionen timeit, Bestimmen von Laufzeiten turtle, Schildkrötengrafik wave, Bearbeitungen von Wave-Dateien webbrowser, Zugriff auf Webseiten xml, Bearbeiten von XML-Dateien csv, Bearbeiten von Komma-getrennten Daten und es gibt noch viele mehr. PRG, SS 13 May 27, 2013 21