Brett Slatkin Effektiv Python programmieren 59 Wege für bessere Python-Programme Übersetzung aus dem Amerikanischen von Knut Lorenzen Bibliografische Information der Deutschen Nationalbibliothek Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über <http://dnb.d-nb.de> abrufbar. ISBN 978-3-95845-182-7 1. Auflage 2015 www.mitp.de E-Mail: [email protected] Telefon: +49 7953 / 7189 - 079 Telefax: +49 7953 / 7189 - 082 © 2015 mitp Verlags GmbH & Co. KG Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Verarbeitung in elektronischen Systemen. Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Werk berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften. Authorized Translation from the English language edition, entitled EFFECTIVE PYTHON: 59 SPECIFIC WAYS TO WRITE BETTER PYTHON, 1st Edition by BRETT SLATKIN, published by Pearson Education, Inc, publishing as Addison-Wesley Professional, Copyright © 2015 Pearson Education, Inc. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc. GERMAN language edition published by mitp Verlags GmbH & Co KG Copyright © 2015. Lektorat: Sabine Schulz Sprachkorrektorat: Petra Heubach-Erdmann Coverbild: Chuti Prasertsith Satz: III-satz, Husby, www.drei-satz.de Der Familie, geliebt und verloren. Inhaltsverzeichnis 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13 2 2.1 2.2 2.3 2.4 2.5 2.6 Vorwort. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Über den Autor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Danksagungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Pythons Sicht der Dinge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 1: Kenntnis der Python-Version . . . . . . . . . . . . . . . . . . . . . . . . Punkt 2: Stilregeln gemäß PEP 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 3: Unterschiede zwischen bytes, str und unicode . . . . . . . . . . Punkt 4: Hilfsfunktionen statt komplizierter Ausdrücke. . . . . . . . . . Punkt 5: Zugriff auf Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 6: Verzicht auf Abstand und Start-/End-Index . . . . . . . . . . . . Punkt 7: Listen-Abstraktionen statt map und filter. . . . . . . . . . . . . . . Punkt 8: Nicht mehr als zwei Ausdrücke in Listen-Abstraktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 9: Generator-Ausdrücke in Listen-Abstraktionen . . . . . . . . . . Punkt 10: enumerate statt range . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 11: Gleichzeitige Verarbeitung von Iteratoren mit zip. . . . . . . Punkt 12: Verzicht auf else-Blöcke nach for- und while-Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 13: Alle Blöcke einer try/except/else/finally-Anweisung nutzen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 17 19 21 24 27 30 32 Funktionen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 14: Exceptions statt Rückgabe von None . . . . . . . . . . . . . . . . . Punkt 15: Closures und der Gültigkeitsbereich von Variablen. . . . . . Punkt 16: Generatoren statt Rückgabe von Listen . . . . . . . . . . . . . . . Punkt 17: Vorsicht beim Iterieren über Argumente . . . . . . . . . . . . . . Punkt 18: Klare Struktur dank variabler Argumente . . . . . . . . . . . . . Punkt 19: Optionale Funktionalität durch SchlüsselwortArgumente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 49 51 57 59 64 34 36 38 39 42 45 67 7 Inhaltsverzeichnis 2.7 2.8 3 3.1 3.2 3.3 3.4 3.5 3.6 3.7 4 4.1 4.2 4.3 4.4 4.5 4.6 4.7 5 5.1 5.2 5.3 5.4 5.5 5.6 6 6.1 6.2 6.3 8 Punkt 20: Dynamische Standardwerte von Argumenten mittels None und Docstrings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 21: Eindeutigkeit durch Schlüsselwort-Argumente . . . . . . . . . Klassen und Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 22: Hilfsklassen statt Dictionaries und Tupel . . . . . . . . . . . . . Punkt 23: Funktionen statt Klassen bei einfachen Schnittstellen . . . Punkt 24: Polymorphismus und generische Erzeugung von Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 25: Initialisierung von Basisklassen durch super. . . . . . . . . . . Punkt 26: Mehrfache Vererbung nur für Mix-in-Hilfsklassen . . . . . Punkt 27: Öffentliche statt private Attribute . . . . . . . . . . . . . . . . . . . . Punkt 28: Benutzerdefinierte Container-Klassen durch Erben von collections.abc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 73 79 79 85 89 95 100 105 110 Metaklassen und Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 29: Einfache Attribute statt Getter- und Setter-Methoden . . . Punkt 30: @property statt Refactoring von Attributen . . . . . . . . . . . . Punkt 31: Deskriptoren für wiederverwendbare @property-Methoden verwenden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 32: Verzögerte Zuweisung zu Attributen mittels __getattr__, __getattribute__ und __setattr__ . . . . . . . . . . . . . . . . . . . Punkt 33: Unterklassen mit Metaklassen überprüfen. . . . . . . . . . . . . Punkt 34: Klassen mittels Metaklassen registrieren . . . . . . . . . . . . . . Punkt 35: Zugriff auf Klassenattribute mit Metaklassen . . . . . . . . . . 115 115 120 Nebenläufigkeit und parallele Ausführung . . . . . . . . . . . . . . . . . . . . . Punkt 36: Verwaltung von Kindprozessen mittels subprocess . . . . . Punkt 37: Threads, blockierende Ein-/Ausgabevorgänge und parallele Ausführung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 38: Wettlaufsituationen in Threads mit Lock verhindern . . . . Punkt 39: Threads koordinieren mit Queue . . . . . . . . . . . . . . . . . . . . Punkt 40: Parallele Ausführung mehrerer Funktionen mit Coroutinen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 41: Echte parallele Ausführung mit concurrent.futures . . . . . 147 148 Standardmodule. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 42: Funktions-Decorators mit functools.wraps definieren . . . Punkt 43: contextlib und with-Anweisung statt try/finally-Konstrukt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 44: Verlässliches pickle durch copyreg . . . . . . . . . . . . . . . . . . . 185 185 124 130 136 138 143 152 157 160 169 179 188 192 Inhaltsverzeichnis 6.4 6.5 6.6 6.7 7 7.1 7.2 7.3 7.4 7.5 8 8.1 8.2 8.3 8.4 8.5 8.6 Punkt 45: Für örtliche Zeitangaben datetime statt time verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 46: Verwendung von Algorithmen und Datenstrukturen der Standardbibliothek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 47: Falls Genauigkeit an erster Stelle steht, decimal verwenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 48: Module der Python-Community. . . . . . . . . . . . . . . . . . . . . Zusammenarbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 49: Docstrings für sämtliche Funktionen, Klassen und Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 50: Pakete zur Organisation von Modulen und zur Bereitstellung stabiler APIs verwenden. . . . . . . . . . . . . . . . . . . . . . . . Punkt 51: Einrichten einer Root-Exception zur Abschottung von Aufrufern und APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 52: Zirkuläre Abhängigkeiten auflösen . . . . . . . . . . . . . . . . . . Punkt 53: Virtuelle Umgebungen zum Testen von Abhängigkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 203 208 210 213 213 218 223 227 233 Veröffentlichung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 54: Modulbezogener (Module-scoped) Code zur Konfiguration der Deployment-Umgebung . . . . . . . . . . . . . . . . . . . . Punkt 55: Debuggen mit repr-Strings . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 56: Überprüfung mit unittest . . . . . . . . . . . . . . . . . . . . . . . . . . Punkt 57: Interaktives Debuggen mit pdb . . . . . . . . . . . . . . . . . . . . . . Punkt 58: Vor der Optimierung Messungen vornehmen . . . . . . . . . Punkt 59: Nutzung des Arbeitsspeichers und Speicherlecks mit tracemalloc untersuchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 244 247 251 253 Stichwortverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 241 258 9 Vorwort Die Programmiersprache Python besitzt einzigartige Stärken und Vorteile, die nicht immer ganz einfach zu verstehen sind. Mit anderen Sprachen vertraute Programmierer nähern sich Python oftmals nur zögerlich, anstatt die enorme Ausdrucksfähigkeit willkommen zu heißen. Andere übertreiben in entgegengesetzter Richtung und überstrapazieren Python-Funktionalitäten, was später große Probleme verursachen kann. Dieses Buch möchte Ihnen einen Einblick geben in das, was im Englischen als pythonic (»Python-artig«) bezeichnet wird: die beste Art und Weise, Python zu verwenden. Dieser Programmierstil setzt grundlegende Kenntnisse der Sprache voraus, über die Sie, wie ich annehme, bereits verfügen. Programmieranfänger lernen die bewährten Vorgehensweisen zur Nutzung von Pythons Fähigkeiten kennen. Erfahrene Programmierer hingegen erfahren, wie sie souverän mit den Eigenheiten dieses neuen Werkzeugs zurechtkommen. Ich möchte Sie darauf vorbereiten, mit Python große Wirkung zu erzielen. Inhalt des Buches In den einzelnen Kapiteln des Buches sind verschiedene Punkte aufgeführt, die jeweils weit gefasste, aber doch verwandte Themen betreffen. Es steht Ihnen frei, ganz nach Ihrem Interesse im Buch herumzublättern. Jeder Punkt enthält kompakte und präzise Anleitungen, die Ihnen dabei helfen sollen, effektivere PythonProgramme zu schreiben. Sie finden dort Ratschläge, was zu tun und was besser zu lassen ist, Hinweise zum Eingehen von Kompromissen und Erklärungen, warum das eine oder das andere die bessere Wahl ist. Die Themen sind auf die Python-Versionen 2 und 3 zugeschnitten (siehe Punkt 1: Kenntnis der Python-Version). Der größte Teil der Punkte ist auch für alternative Laufzeitumgebungen wie Jython, IronPython oder PyPy gültig. Kapitel 1: Pythons Sicht der Dinge In der Python-Community dient das englische Adjektiv pythonic zur Beschreibung von Code, der einem bestimmten Programmierstil folgt. Dieser Stil hat sich im Laufe der Zeit durch Erfahrung im Umgang mit der Sprache und die Zusammenarbeit der Community allmählich entwickelt. Dieses Kapitel beschreibt die beste Art und Weise, die gängigsten Aufgaben in Python zu erledigen. 11 Vorwort Kapitel 2: Funktionen In Python besitzen Funktionen eine Vielzahl von Merkmalen, die einem Programmierer das Leben erleichtern. Einige sind den Fähigkeiten anderer Programmiersprachen ähnlich, viele gibt es jedoch nur in Python. Dieses Kapitel hat zum Thema, wie man Funktionen dazu verwendet, ihren Zweck zu verdeutlichen, ihre Wiederverwendung zu ermöglichen und Bugs zu vermeiden. Kapitel 3: Klassen und Vererbung Python ist eine objektorientierte Programmiersprache. Um Aufgaben in Python zu erledigen, ist es oft erforderlich, neue Klassen anzulegen und zu definieren, wie sie mittels ihrer Schnittstellen und der Klassenhierarchie miteinander interagieren. Dieses Kapitel erläutert, wie man Klassen und Vererbung zur Modellierung des beabsichtigten Verhaltens durch Objekte nutzt. Kapitel 4: Metaklassen und Attribute Metaklassen und dynamische Attribute sind leistungsfähige Python-Merkmale, die es allerdings auch ermöglichen, äußerst merkwürdiges und unerwartetes Verhalten zu implementieren. Dieses Kapitel stellt die üblichen Verwendungsweisen dieser Mechanismen vor, damit Sie dem Prinzip der geringsten Überraschung folgen können. Kapitel 5: Nebenläufigkeit und parallele Ausführung In Python können schnell und einfach Programme geschrieben werden, die scheinbar mehrere Aufgaben gleichzeitig erledigen. Python kann außerdem durch Systemaufrufe, Subprozesse oder C-Erweiterungen Code parallel ausführen. Dieses Kapitel führt vor, wie sich diese leicht unterschiedlichen Verfahren am besten einsetzen lassen. Kapitel 6: Standardmodule Python bringt eine Reihe wichtiger Module mit, auf die Sie bei der Programmierung zurückgreifen können. Diese Standardpakete sind in Python so gebräuchlich, dass sie sehr wohl auch Bestandteil der Sprache selbst sein könnten. In diesem Kapitel werden die grundlegenden integrierten Module vorgestellt. Kapitel 7: Zusammenarbeit Bei der gemeinsamen Entwicklung von Python-Programmen muss dem Programmierstil Beachtung geschenkt werden. Selbst wenn Sie der einzige Programmierer sind, müssen Sie doch wissen, wie die von anderen Entwicklern erstellten Module verwendet werden. Dieses Kapitel behandelt die Standard- 12 Konventionen dieses Buches werkzeuge und bewährte Vorgehensweisen, die es ermöglichen, gemeinsam an Python-Programmen zu arbeiten. Kapitel 8: Veröffentlichung Python-Programme können flexibel an verschiedene Benutzerumgebungen angepasst werden. Darüber hinaus gibt es integrierte Module, die Ihnen dabei helfen, Ihr Programm abzusichern und belastbar zu machen. Dieses Kapitel führt vor, wie Sie Python zum Debuggen, zur Optimierung und zum Testen Ihrer Programme einsetzen können, um die Qualität und Performance zur Laufzeit zu maximieren. Konventionen dieses Buches Die Codebeispiele in diesem Buch sind in einer nicht-proportionalen Schrift gedruckt. Ich habe mir hinsichtlich der üblichen Python-Stilregeln eine gewisse »künstlerische Freiheit« genommen, um die Darstellung an die Gegebenheiten eines Buches anzupassen. Wenn lange Zeilen umbrochen werden müssen, verwende ich zur Markierung das Zeichen »\«. Weggelassene Codeabschnitte sind durch einen Kommentar mit Auslassungszeichen (# ...) gekennzeichnet. Er weist darauf hin, dass weiterer Code vorhanden ist, der im gegebenen Zusammenhang jedoch nicht von Bedeutung ist. Außerdem habe ich aus Platzgründen die Docstrings entfernt. Das sollten Sie in Ihren eigenen Projekten allerdings nicht tun – folgen Sie besser den üblichen Stilregeln (siehe Punkt 2: Stilregeln gemäß PEP 8) und dokumentieren Sie Ihren Code (siehe Punkt 49: Docstrings für sämtliche Funktionen, Klassen und Module). Viele Codeabschnitte enthalten auch die bei der Ausführung des Codes erfolgenden Ausgaben. Damit sind die Ausgaben auf der Konsole oder im Terminalfenster gemeint, die erscheinen, wenn das Programm im interaktiven Python-Interpreter ausgeführt wird. Vor den in nicht-proportionaler Schrift gedruckten Ausgaben steht eine Zeile mit den Zeichen >>> (die interaktive Python-Eingabeaufforderung). Dem liegt der Gedanke zugrunde, dass Sie die Beispiele in einer PythonShell eingeben und die Ausgaben reproduzieren können. Schließlich gibt es noch weitere Abschnitte in nicht-proportionaler Schrift ohne führende >>>-Zeile. Sie stellen Ausgaben des laufenden Programms dar (nicht des Interpreters). Am Anfang der Beispiele steht oftmals ein Dollarzeichen ($), das darauf hinweist, dass ich Programme von einer Shell wie Bash aus starte. Beispielcode herunterladen Manche Beispiele in diesem Buch sollten besser als komplette Programme ohne die eingestreuten Texte betrachtet werden. Sie können sich den Quellcode auf der 13 Vorwort Website zum Buch (http://www.effectivepython.com) herunterladen. Sie haben dann auch die Möglichkeit, mit dem Code herumzuexperimentieren und die Funktionsweise besser zu verstehen. 14 Über den Autor Brett Slatkin ist bei Google als Führungskraft in der Softwareentwicklung tätig. Er ist leitender Ingenieur und Mitbegründer des Projekts Google Consumer Surveys. Früher arbeitete er an der Python-Infrastruktur von Googles App Engine. Er ist Miterfinder des PubSubHubbub-Protokolls. Vor neun Jahren sammelte er bei der Verwaltung von Googles riesigem Serverbestand erste Erfahrungen mit Python. Neben der alltäglichen Arbeit widmet er sich Open-Source-Projekten und schreibt auf seiner privaten Website (http://www.onebigfluke.com) über Software, Fahrräder und andere Themen. Er erwarb seinen Bachelor of Science in technischer Informatik an der Columbia Universität in New York und lebt in San Francisco. Danksagungen Ohne die Hilfe, Unterstützung und den Zuspruch vieler Menschen würde es dieses Buch nicht geben. Dank an Scott Meyers für die Buchreihe Effective Software Development. Als ich 15 Jahre alt war, habe ich erstmals Effective C++ gelesen und es war um mich geschehen. Es besteht kein Zweifel daran, dass Scotts Bücher zu meiner akademischen Laufbahn und meiner ersten Anstellung bei Google geführt haben. Ich bin begeistert, dass ich die Möglichkeit hatte, dieses Buch zu schreiben. Dank an die technischen Korrekturleser für ihre ausführlichen und gründlichen Rückmeldungen: Brett Cannon, Tavis Rudd und Mike Taylor. Dank an Leah Culver und Adrian Holovaty, die das Buch für eine gute Idee hielten. Dank an meine Freunde, die geduldig die ersten Versionen des Buches lasen: Michael Levine, 15