Dane oryginału

Copyright © 2019 by Lee Vaughan. Title of English-language original: Impractical Python Projects: Playful Programming Activities to Make You Smarter, ISBN 978-1-59327-890-8, published by No Starch Press. Polish-language edition copyright © 2020 by Polish Scientific Publishers PWN Wydawnictwo Naukowe PWN Spółka Akcyjna. All rights reserved.

Przekład Krzysztof Kapustka na zlecenie WITKOM Witold Sikorski

Projekt okładki polskiego wydania Joanna Andryjowicz na podstawie oryginału

Wydawca Edyta Kawala

Redaktor prowadzący Jolanta Kowalczuk

Redaktor Małgorzata Dąbkowska-Kowalik

Koordynator produkcji Anna Bączkowska

Skład wersji elektronicznej na zlecenie Wydawnictwa Naukowego PWN

Monika Lipiec / Woblink

Zastrzeżonych nazw firm i produktów użyto w książce wyłącznie w celu identyfikacji.

Copyright © for the Polish edition by Wydawnictwo Naukowe PWN SA

Warszawa 2020

ISBN 978-83-01-20998-8

eBook został przygotowany na podstawie wydania papierowego z 2020 r., (wyd. I)

Warszawa 2020

Wydawnictwo Naukowe PWN SA

02-460 Warszawa, ul. Gottlieba Daimlera 2

tel. 22 69 54 321, faks 22 69 54 288

infolinia 801 33 33 88

e-mail: pwn@pwn.com.pl; reklama@pwn.pl

www.pwn.pl

Dla przypadkowych programistów,

zdeterminowanych niespecjalistów i entuzjastów:

wszystkich amatorów, którzy piszą kod każdego dnia.

Niech ta książka Wam pomoże.

O autorze

Lee Vaughan jest geologiem z ponad 30-letnim doświadczeniem w przemyśle naftowym. Pracując jako starszy profesjonalista techniczny przy modelowaniu geologicznym w głównych międzynarodowych spółkach naftowych, Lee był zaangażowany w tworzenie i przegląd modeli komputerowych, rozwój, testowanie i komercjalizację oprogramowania, a także szkolenie geologów i inżynierów. Wspiera osoby nieprogramujące, które muszą korzystać z programowania w swojej pracy. Niepraktyczne projekty w Pythonie napisał, aby pomóc samoukom w doskonaleniu ich umiejętności z użyciem języka Python.

O recenzencie technicznym

Jeremy Kun uzyskał tytuł doktora na Uniwersytecie Illinois w Chicago. Prowadzi blog Math ∩ Programming (https://jeremykun.com/) i obecnie pracuje przy optymalizacji centrów danych w Google.

Spis treści

Podziękowania

Wprowadzenie

Dla kogo jest ta książka?

Co jest w tej książce?

Wersja Pythona, platforma i IDE

Kod

Styl kodu

Gdzie uzyskać pomoc?

Naprzód!

1. Generator zabawnych pseudonimów

Projekt 1: Generowanie pseudonimów

Planowanie i tworzenie projektu

Strategia

Pseudokod

Kod

Korzystanie z przewodnika po stylach tworzonego przez społeczność Pythona

Sprawdzanie kodu za pomocą narzędzia Pylint

Opisywanie kodu za pomocą ciągów docstring

Sprawdzanie stylu naszego kodu

Podsumowanie

Materiały dodatkowe

Pseudokod

Przewodniki po stylach

Moduły zewnętrzne

Ćwiczenia

Świńska łacina

Wykres słupkowy dla języka angielskiego

Wyzwania

Wykres słupkowy dla języków romańskich

Drugie imię

Coś całkowicie innego

2. Znajdowanie zaklęć

Znajdowanie i otwieranie słownika

Obsługiwanie wyjątków podczas otwierania plików

Wczytywanie pliku słownika

Projekt 2: Znajdowanie palindromów

Strategia i pseudokod

Palindromy

Projekt 3: Znajdowanie palindromów wielowyrazowych

Strategia i pseudokod

Palindromy wielowyrazowe – kod

Profilowanie palindromów

Optymalizacja palindromów

ceinoK

Materiały dodatkowe

Ćwiczenie: oczyszczanie słownika

Wyzwanie: podejście rekurencyjne

3. Rozwiązywanie anagramów

Projekt 4: Znajdowanie anagramów jednowyrazowych

Strategia i pseudokod

Znajdowanie anagramów – kod

Projekt 5: Znajdowanie anagramów wielowyrazowych

Strategia i pseudokod

Kod anagramów wielowyrazowych

Projekt 6: Znajdowanie Voldemorta – galijski gambit

Projekt 7: Znajdowanie Voldemorta: brytyjska metoda siłowa

Strategia

Kod brytyjskiej metody siłowej

Podsumowanie

Materiały dodatkowe

Ćwiczenie: znajdowanie dwuznaków

Wyzwanie: automatyczny generator anagramów

4. Dekodowanie szyfrów z amerykańskiej wojny domowej

Projekt 8: Szyfr trasowy

Strategia

Pseudokod

Dekodowanie szyfru trasowego – kod

Łamanie szyfru trasowego

Dodawanie interfejsu użytkownika

Projekt 9: Szyfr płotkowy

Strategia

Szyfrowanie szyfrem płotkowym – kod

Dekodowanie szyfru płotkowego – kod

Podsumowanie

Materiały dodatkowe

Ćwiczenia

Rozszyfrowywanie komunikatu Lincolna

Identyfikowanie rodzajów szyfrów

Przechowywanie klucza w formie słownika

Automatyzowanie możliwych kluczy

Przestawieniowy szyfr trasowy: atak siłowy

Wyzwania

Narzędzie do kodowania szyfrem trasowym

Szyfr płotkowy z trzema sztachetami

5. Kodowanie szyfrów z brytyjskiej wojny domowej

Projekt 10: Szyfr Trevaniona

Strategia i pseudokod

Szyfr Trevaniona – kod

Projekt 11: Pisanie ukrytej wiadomości

Szyfr listowy – kod

Szyfr listowy – wynik

Podsumowanie

Materiały dodatkowe

Ćwiczenia

Ratowanie Marii

Złapanie w zamku Colchester

6. Pisanie atramentem sympatycznym

Projekt 12: Ukrywanie szyfru Vigenère’a

Platforma

Strategia

Tworzenie atramentu sympatycznego

Operowanie dokumentami programu Word z użyciem modułu python-docx

Pobieranie zasobów

Pseudokod

Kod

Formatowanie i przeplatanie wiadomości

Dodawania szyfru Vigenère’a

Wykrywanie ukrytej wiadomości

Podsumowanie

Materiały dodatkowe

Ćwiczenie: sprawdzanie liczby pustych wierszy

Wyzwanie: korzystanie z czcionki o stałej szerokości znaków

7. Hodowanie olbrzymich szczurów za pomocą algorytmów genetycznych

Znajdowanie najlepszego rozwiązania

Projekt 13: Hodowanie armii superszczurów

Strategia

Superszczury – kod

Podsumowanie

Projekt 14: Łamanie kodu zaawansowanego technicznie sejfu

Strategia

Łamacz sejfów – kod

Podsumowanie

Materiały dodatkowe

Wyzwania

Tworzenie szczurzego haremu

Tworzenie bardziej wydajnego łamacza kodów sejfów

8. Zliczanie sylab w wierszach haiku

Japońskie haiku

Projekt 15: Zliczanie sylab

Strategia

Korzystanie z korpusu

Instalowanie NLTK

Pobieranie słownika CMUdict

Zliczanie dźwięków zamiast sylab

Obsługiwanie słów z więcej niż jedną wymową

Zarządzanie brakującymi słowami

Korpus szkoleniowy

Brakujące słowa – kod

Zliczanie sylab – kod

Przygotowanie, wczytywanie i zliczanie

Definiowanie funkcji main()

Program do sprawdzania naszego programu

Podsumowanie

Materiały dodatkowe

Ćwiczenie: zliczanie sylab a plik słownika

9. Pisanie Haiku z użyciem łańcuchów Markowa

Projekt 16: Analiza z użyciem łańcuchów Markowa

Strategia

Wybieranie i odrzucanie słów

Kontynuacja z jednego wersu do drugiego

Pseudokod

Korpus szkoleniowy

Debugowanie

Budowanie rusztowania

Rejestrowanie za pomocą modułu logging

Kod

Przygotowanie

Tworzenie modeli Markowa

Wybieranie losowego słowa

Stosowanie modeli Markowa

Generowanie wersów haiku

Pisanie interfejsu użytkownika

Wyniki

Dobre haiku

Inicjator haiku

Podsumowanie

Materiały dodatkowe

Wyzwania

Generator nowych słów

Test Turinga

Niewiarygodne! To niewiarygodne! Niewiarygodne!

Haikować czy nie haikować

Muzyka Markowa

10. Czy jesteśmy sami? Poznawanie paradoksu Fermiego

Projekt 17: Modelowanie Drogi Mlecznej

Strategia

Szacowanie liczby cywilizacji

Wybieranie rozmiaru bąbla fal radiowych

Generowanie wzoru dla prawdopodobieństwa wykrycia

Prawdopodobieństwo wykrycia – kod

Obliczanie prawdopodobieństwa wykrycia dla zakresu cywilizacji

Generowanie wzoru predykcyjnego i sprawdzanie rezultatów

Tworzenie modelu graficznego

Skalowanie modelu graficznego

Symulator galaktyki – kod

Rezultaty

Podsumowanie

Materiały dodatkowe

Ćwiczenia

Bardzo odległa galaktyka

Tworzenie galaktycznego imperium

Okrężny sposób przewidywania wykrywalności

Wyzwania

Tworzenie galaktyki spiralnej z poprzeczką

Dodawanie stref zamieszkiwalnych do naszej galaktyki

11. Problem Monty’ego Halla

Symulacja Monte Carlo

Projekt 18: Weryfikacja vos Savant

Strategia

Weryfikacja vos Savant – kod

Projekt 19: Gra Monty’ego Halla

Krótkie wprowadzenie do programowania obiektowego

Strategia i pseudokod

Zasoby gry

Gra Monty’ego Halla – kod

Podsumowanie

Materiały dodatkowe

Ćwiczenie: paradoks dnia urodzin

12. Zabezpieczanie kwoty na specjalny cel

Projekt 20: Symulowanie życia na emeryturze

Strategia

Historyczne zwroty mają znaczenie

Największa niepewność

Jakościowy sposób prezentowania wyników

Pseudokod

Wyszukiwanie danych historycznych

Kod

Importowanie modułów i definiowanie funkcji do wczytywania i pobierania danych od użytkownika

Pobieranie danych od użytkownika

Sprawdzanie pod kątem pozostałych błędów

Definiowanie silnika Monte Carlo

Symulowanie każdego roku w przypadku

Obliczanie prawdopodobieństwa ruiny

Definiowanie i wywoływanie funkcji main()

Korzystanie z symulatora

Podsumowanie

Materiały dodatkowe

Wyzwania

Obraz jest wart tysiąca dolarów

Mieszanka

Po prostu mam szczęście!

Cała pula

13. Symulowanie pozaziemskiego wulkanu

Projekt 21: Pióropusze Io

Pakiet pygame

Strategia

Planowanie za pomocą szkicu gry

Planowanie klasy Particle

Kod

Importowanie modułów, inicjalizacja pygame i definiowanie kolorów

Definiowanie klasy Particle

Wyrzucanie cząsteczki

Aktualizowanie cząsteczki i obsługa warunków brzegowych

Definiowanie funkcji main()

Kończenie funkcji main()

Uruchamianie symulacji

Podsumowanie

Materiały dodatkowe

Ćwiczenie: odległość

Wyzwania

Baldachim pióropusza

Źródło

Pocisk

14. Odwzorowywanie Marsa przy użyciu sondy Mars Orbiter

Astrodynamika dla graczy

Prawo powszechnego ciążenia

Prawo Keplera dotyczące ruchu planet

Mechanika orbitalna

Projekt 22: Gra Mars Orbiter

Strategia

Zasoby gry

Kod

Importowanie i tworzenie tabeli kolorów

Definiowanie metody inicjalizacyjnej klasy Satellite

Ustawianie początkowego położenia, prędkości, paliwa i dźwięku dla satelity

Odpalanie silników i oczekiwanie na reakcję gracza

Lokalizowanie satelity

Obracanie satelity i rysowanie jego orbity

Aktualizowanie obiektu satelity

Definiowanie metody inicjalizacyjnej klasy Planet

Obracanie planety

Definiowanie metod gravity() i update()

Obliczanie mimośrodu

Definiowanie funkcji do tworzenia etykiet

Odwzorowanie wilgotności gleby

Rzucanie cienia

Definiowanie funkcji main()

Tworzenie obiektów, przygotowywanie weryfikacji orbity, odwzorowywania i pomiarów czasu

Rozpoczynanie pętli gry i odtwarzanie dźwięków

Stosowanie grawitacji, obliczanie mimośrodu i obsługiwanie porażek

Nagradzanie sukcesu oraz aktualizowanie i rysowanie duszków

Wyświetlanie instrukcji i telemetrii oraz rzucanie cienia

Podsumowanie

Wyzwania

Ekran tytułowy gry

Inteligentne wskaźniki

Zanik łączności

Punkty

Przewodnik strategiczny

Hamowanie aerodynamiczne

Alarm o intruzie!

Z góry

15. Poprawianie astrofotografii za pomocą uśredniania planet

Projekt 23: Uśrednianie Jowisza

Moduł pillow

Praca z plikami i folderami

Ścieżki do katalogów

Moduł Shell Utilities

Wideo

Strategia

Kod

Kadrowanie i skalowanie

Uśrednianie

Poprawianie

Podsumowanie

Materiały dodatkowe

Wyzwanie: zniknięcie

16. Wykrywanie oszustw za pomocą Prawa Benforda

Projekt 24: Prawo Benforda dotyczące pierwszych cyfr

Stosowanie prawa Benforda

Wykonywanie testu chi kwadrat

Zbiór danych

Strategia

Kod

Importowanie modułów i wczytywanie danych

Zliczanie pierwszych cyfr

Pobieranie oczekiwanych liczników

Ustalanie zgodności rozkładów

Definiowane funkcji wykresu słupkowego

Kończenie funkcji wykresu słupkowego

Definiowanie i uruchamianie funkcji main()

Podsumowanie

Materiały dodatkowe

Ćwiczenie: pokonywanie Benforda

Wyzwania

Stosowanie prawa Benforda w wahających się stanach

Gdy nikt nie patrzył

Dodatek: Rozwiązania ćwiczeń

Rozdział 1: Generator zabawnych pseudonimów

Rozdział 2: Znajdowanie zaklęć

Rozdział 3: Rozwiązywanie anagramów

Rozdział 4: Dekodowanie szyfrów z amerykańskiej wojny domowej

Rozdział 5: Kodowanie szyfrów z brytyjskiej wojny domowej

Rozdział 6: Pisanie atramentem sympatycznym

Rozdział 8: Zliczanie sylab w wierszach haiku

Rozdział 10: Czy jesteśmy sami? Odkrywanie paradoksu Fermiego

Rozdział 11: Problem Monty’ego Halla

Rozdział 13: Symulowanie pozaziemskiego wulkanu

Rozdział 16: Znajdowanie oszustw za pomocą prawa Benforda

Przypisy

Podziękowania

Pisanie książki jest sprawą rodzinną, a ja nie mógłbym tego dokonać bez wsparcia ze strony zarówno mojej prawdziwej rodziny, jak i rodziny zastępczej w wydawnictwie No Starch Press. Przede wszystkim chciałbym podziękować mojej żonie, Hannah, a także moim córkom, Sarze i Lorze, za ich wyrozumiałość, cierpliwość i nieustanne wsparcie w redagowaniu.

Dziękuję pracownikom wydawnictwa No Starch, Billowi Polockowi i Tylerowi Ortmanowi, za przyjęcie mojej propozycji, Zachowi Lebowskiemu za nadanie sensu temu, co chciałem przekazać, Janelle Ludowise za wysoce profesjonalną pracę nad edycją produkcji, Rachel Monaghan i Pauli Fleming za ciężką pracę nad adjustacją i korektą książki technicznej, Davidowi Van Nessowi za skład oraz Serenie Yang i Joshowi Ellingsonowi za wspaniały projekt okładki. Dziękuję również moim technicznym recenzentom, Jeremy’emu Kunowi, Michaelowi Contraveosowi i Michele Pratusevich za znaczne ulepszenie tej książki dzięki bezcennym sugestiom i poprawkom.

Poza osobami z No Starch, dużego wsparcia technicznego udzielili mi Sarah Vaughan, Eric Evenchick, Xiao-Hui Wu, Brooks Clark, Brian Proett, Brent Francis i Glenn Krum.

Na koniec dziękuję Markowi Nathernowi za wprowadzenie mnie do języka Python, a także Guido van Rossumowi za stworzenie tego języka!

Wprowadzenie

Witamy w książce Python mniej poważnie. Korzystając z języka programowania Python, będziemy w niej odkrywać Marsa, Jowisza i najdalsze zakątki galaktyki, dusze poetów, świat wielkich finansów, podziemia szpiegostwa i fałszowania głosów, oszustwa w teleturniejach i znacznie więcej. Użyjemy łańcuchów Markowa do napisania haiku, symulacji Monte Carlo do modelowania rynków finansowych, uśredniania obrazów do usprawnienia naszej astrofotografii oraz algorytmów

genetycznych do wyhodowania armii gigantycznych szczurów, zdobywając jednocześnie doświadczenie w pracy z takimi modułami jak pygame, Pylint, pydocstyle, tkinter, python-docx, matplotlib i pillow. Przede wszystkim jednak będziemy się dobrze bawić.

Dla kogo jest ta książka?

Książkę tę można traktować jako drugi podręcznik do nauki Pythona. Została ona zaprojektowana w taki sposób, aby można ją było wykorzystywać jako uzupełnienie książki dla początkujących lub kursu wprowadzającego. Dzięki niej można będziesz w stanie kontynuować samodzielną naukę, stosując podejście oparte na projektach, bez marnowania pieniędzy lub miejsca na półce na dokładne przerabianie pojęć, które już znasz. Nie martw się jednak, że zostaniesz bez pomocy – cały kod jest odpowiednio opisany i objaśniony.

Projekty te przeznaczone są dla każdego, kto chce używać programowania do przeprowadzania eksperymentów, testowania teorii, symulowania natury lub po prostu do zabawy. Mowa tutaj również o osobach, które wykorzystują programowanie w swojej pracy (np. naukowcy lub inżynierowie), ale które nie są tak naprawdę programistami, a także osobach, które nazywam „zdeterminowanymi niespecjalistami” – dyletantami i amatorami, którzy czerpią przyjemność z rozwiązywania problemów programistycznych w wolnym czasie. Jeśli chciałeś pobawić się prezentowanymi tu koncepcjami, ale rozpoczynanie potencjalnie skomplikowanych projektów od zera uznałeś za zbyt trudne lub czasochłonne, to ta książka jest dla Ciebie.

Co jest w tej książce?

W miarę wykonywania tych projektów, będziesz pogłębiać swoją wiedzę na temat przydatnych bibliotek i modułów języka Python, poznawać nowe skróty, wbudowane funkcje i pomocne techniki, a także ćwiczyć projektowanie, testowanie i optymalizowanie programów. Dodatkowo będziesz w stanie przełożyć wykonywaną pracę na rzeczywiste aplikacje, zbiory danych i problemy.

Cytując Ralpha Waldo Emersona, „nigdy nie osiągnięto niczego wielkiego bez entuzjazmu”, a dotyczy to również uczenia się. Ostatecznym celem tej książki jest pobudzić Twoją wyobraźnię i pomóc Ci samodzielnie rozwijać interesujące projekty. Nie przejmuj się, jeśli na początku będą Ci się one wydawać zbyt ambitne. Odrobina staranności połączona z dużą ilością googlowania mogą zdziałać cuda – i to dużo szybciej niż myślisz

Poniżej znajduje się krótkie omówienie rozdziałów zawartych w tym podręczniku. Nie musisz czytać ich po kolei, ale najłatwiejsze projekty znajdują się na początku książki, a do tego nowe pojęcia, moduły i techniki omawiam bardziej szczegółowo, gdy są one prezentowane po raz pierwszy.

Rozdział 1: Generator zabawnych pseudonimów Ten „rozgrzewkowy” projekt wprowadza przewodniki po stylach Python PEP 8 i PEP 257, jak również moduły Pylint i pydocstyle, które analizują zgodność naszego kodu z tymi wskazówkami. Końcowym produktem jest generator zabawnych pseudonimów zainspirowany serialem telewizyjnym Psych.

Rozdział 2: Znajdowanie zaklęć Naucz się profilować swój kod, starając się uchronić czarodziejkę Zatannę przed bolesną śmiercią. Przeszukaj słowniki online pod kątem magicznych palindromów wielowyrazowych, których Zatanna potrzebuje do pokonania cofającego czas wroga.

Rozdział 3: Rozwiązywanie anagramów Napisz program, który pomaga użytkownikowi utworzyć frazę anagramową z jego imienia i nazwiska. Przykładowo Clint Eastwood daje w rezultacie old west action. Następnie pomóż Tomowi Marvolo Riddle’owi utworzyć jego anagram, „I am Lord Voldemort” przy użyciu sit lingwistycznych.

Rozdział 4: Dekodowanie szyfrów z amerykańskiej wojny domowej Zbadaj i złam jeden z najbardziej udanych szyfrów wojskowych w historii – szyfr trasowy Unii. Następnie pomóż szpiegom po obu stronach wysłać i zdekodować sekretne komunikaty za pomocą zygzakującego szyfru płotkowego.

Rozdział 5: Kodowanie szyfrów z brytyjskiej wojny domowej Odczytaj wiadomość ukrytą w tekście, dekodując szyfr z czasów brytyjskiej wojny domowej. Następnie uratuj Marię, królową Szkotów, projektując i stosując kod, który pozwoli jej wykonać trudniejsze zadanie, jakim jest napisanie ukrytej wiadomości.

Rozdział 6: Pisanie atramentem sympatycznym Pomóż kretowi w firmie zdradzić ojca Sherlocka Holmesa i uniknąć wykrycia, wykorzystując do tego celu elektroniczny atrament sympatyczny. Rozdział ten oparty jest na odcinku serialu Elementary.

Rozdział 7: Hodowanie olbrzymich szczurów za pomocą algorytmów genetycznych Użyj algorytmów genetycznych – zainspirowanych ewolucją Darwina – do wyhodowania rasy superszczurów o rozmiarze suczki rasy Bulmastif. Następnie pomóż Jamesowi Bondowi złamać w mgnieniu oka kod sejfu z 10 miliardami możliwych kombinacji.

Rozdział 8: Zliczanie sylab w wierszach haiku Naucz swój komputer zliczać sylaby w języku angielskim jako wstęp do pisania w kolejnym rozdziale japońskich wierszy, nazywanych haiku.

Rozdział 9: Pisanie haiku z użyciem łańcuchów Markowa Naucz swój komputer pisać haiku poprzez połączenie modułu do zliczania sylab z rozdziału 8 z łańcuchami Markowa i korpusem szkoleniowym złożonym z kilkuset starożytnych i nowoczesnych haiku.

Rozdział 10: Czy jesteśmy sami? Poznawanie paradoksu FermiegoZbadaj nieobecność pozaziemskich sygnałów radiowych za pomocą równania Drake’a, wymiary Drogi Mlecznej oraz założenia dotyczące rozmiaru wykrywalnych „bąbli emisji”. Zapoznaj się z popularnym modułem tkinter i wykorzystaj go do utworzenia graficznej reprezentacji galaktyki i własnego bąbla radiowego Ziemi.

Rozdział 11: Problem Monty’ego Halla Pomóż najmądrzejszej kobiecie na świecie wygrać spór dotyczący problemu Monty’ego Halla. Następnie użyj programowania obiektowego do utworzenia wersji popularnej gry Monty’ego z użyciem zabawnego interfejsu graficznego.

Rozdział 12: Zabezpieczanie kwoty na specjalny cel Zaplanuj swoją (lub swoich rodziców) bezpieczną emeryturę za pomocą symulacji finansowej z użyciem metody Monte Carlo.

Rozdział 13: Symulowanie pozaziemskiego wulkanu Użyj modułu pygame do zasymulowania erupcji wulkanicznej na Io, jednym z księżyców Jowisza.

Rozdział 14: Odwzorowywanie Marsa za pomocą sondy Mars Orbiter Zbuduj grę arkadową opartą na grawitacji i spróbuj umieścić satelitę na kołowej orbicie odwzorowywania, starając się przy tym nie zużyć całego paliwa i nie spłonąć w atmosferze. Wyświetlaj odczyty kluczowych parametrów, śledź ścieżki orbitalne, dodaj cień planety i powoli obracaj Marsa wokół jego osi, a wszystko to przy poznawaniu mechaniki orbitalnej!

Rozdział 15: Usprawnianie astrofotografii za pomocą uśredniania planet Ujawnij pasy chmur oraz Wielką Czerwoną Plamę na Jowiszu poprzez optyczne uśrednienie słabej jakości klatek wideo za pomocą biblioteki Pythona do manipulowania obrazami. Naucz się pracować z plikami, folderami i ścieżkami do katalogów przy użyciu wbudowanych modułów os i shutil.

Rozdział 16: Znajdowanie oszustw za pomocą prawa Benforda Użyj prawa Benforda do zbadania fałszerstw w amerykańskich wyborach prezydenckich z 2016 roku. Użyj modułu matplotlib do podsumowania wyników w formie wykresu.

Każdy rozdział kończy się przynajmniej jednym ćwiczeniem lub trudniejszym projektem.

Dla każdego z ćwiczeń podane jest rozwiązanie. Nie oznacza to jednak, że jest to najlepsze rozwiązanie – możliwe, że uda Ci się uzyskać coś lepszego, tak więc nie podglądaj!

W przypadku trudniejszych projektów będziesz jednak zdany wyłącznie na siebie. Gdy Cortez zaatakował Meksyk w 1519 roku, spalił on swoje karawele, tak aby jego konkwistadorzy wiedzieli, że nie ma już drogi powrotnej i że będą oni musieli stawić czoło Aztekom z okrutną i niezachwianą determinacją. Z tego powodu wyrażenie „spalić za sobą mosty” (oryginalnie „burn your boats”, czyli dosł. „spalić swoje łodzie”) oznacza dziś entuzjazm lub pełne zaangażowanie w realizowane zadanie. W taki właśnie sposób należy stawić czoło tym wyzwaniom – jak gdyby Twoje łodzie były spalone. Gdy to zrobisz, prawdopodobnie nauczysz się więcej z tych ćwiczeń niż z jakiejkolwiek innej części tej książki!

Wersja Pythona, platforma i IDE

Każdy z projektów tej książki skonstruowałem przy użyciu Pythona w wersji 3.5 w środowisku Windows 10. Jeśli używasz innego systemu operacyjnego, to nie powinieneś mieć żadnych problemów: w odpowiednich miejscach podaję kompatybilne moduły dla innych platform.

Przykłady kodu oraz zrzuty ekranu prezentowane w tej książce pochodzą albo z edytora tekstowego Python IDLE, albo z powłoki interaktywnej. IDLE to skrót od Integrated Development and Learning Environment. Jest to zintegrowane środowisko programowania (IDE) z dodaną literą L, tak aby akronim ten odnosił się do znanego z Monty Pythona Erica Idle. Powłoka interaktywna, nazywana również interpretatorem, jest oknem, które pozwala na natychmiastowe wykonywanie poleceń i testowanie kodu bez potrzeby tworzenia plików.

IDLE ma jednak kilka wad, takich jak brak kolumny z numerami wierszy, ale jest za to darmowy i dostarczany z Pythonem, więc każdy ma do niego dostęp. Jeśli tylko chcesz, to możesz bez przeszkód używać innego IDE. Do pobrania dostępnych jest wiele innych produktów, takich jak Geany (wymawiane jak angielskie słowo genie), PyCharm czy PyScripter. Geany działa na wielu systemach operacyjnych, łącznie z Uniksem, macOS i Windows. PyCharm działa w Linuksie, systemie Windows i macOS, natomiast PyScripter w systemie Windows. Pełna lista dostępnych narzędzi deweloperskich dla języka Python i kompatybilnych platform znajduje się na stronie https://wiki.python.org/moin/DevelopmentTools/.

Kod

Dla każdego z projektów tej książki podane są wszystkie wiersze kodu. Zachęcam do wprowadzania ich ręcznie wszędzie tam, gdzie to możliwe. Pewien nauczyciel powiedział mi kiedyś, że „uczymy się za pomocą naszych rąk” i muszę się zgodzić, że ręczne wprowadzanie kodu sprawia, iż przykładamy wtedy maksymalną uwagę do tego, co robimy.

Jeśli jednak potrzebujesz szybko całego projektu lub przypadkowo usuniesz całą swoją pracę, to cały jego kod, wraz a rozwiązaniami ćwiczeń, możesz pobrać ze strony https://www.nostarch.com/impracticalpython/.

Styl kodu

Ta książka poświęcona jest rozwiązywaniu problemów i zabawie, tak więc kod może czasami odbiegać od dobrych praktyk i szczytowej wydajności. Okazjonalnie będziemy wykorzystywać wyrażenia listowe lub specjalne operatory, ale w większości przypadków skupimy się na prostym i zrozumiałym kodzie, który ułatwi nam naukę.

Tego rodzaju uproszczenie jest ważne dla programujących nieprogramistów, którzy będą czytać tę książkę. Większość ich kodu może być „kodem Kleenex”, czyli użytym jedno- lub dwukrotnie dla określonego celu, a następnie wyrzuconym. Jest to rodzaj kodu, który może być udostępniony kolegom lub narzucony im z powodu zmian kadrowych, tak więc powinien on być łatwy do czytania i zrozumienia.

Cały główny kod projektów jest opisany i objaśniony w standardowym stylu i zazwyczaj zgodny ze wskazówkami zawartymi w przewodniku Python Enhancement Proposal 8, znanym również jako PEP 8. Szczegóły dotyczące wytycznych PEP 8 i oprogramowania pozwalającego na ich honorowanie znajdują się w rozdziale 1.

Gdzie uzyskać pomoc?

Podejmowanie wyzwania programistycznego może stanowić pewien problem. Kodowanie nie zawsze jest czymś, co możemy intuicyjnie rozgryźć – nawet przy użyciu tak przyjaznego języka jak Python. W ramach kolejnych rozdziałów będę podawał linki i odwołania do przydatnych źródeł informacji, ale w przypadku projektów tworzonych samodzielne nic nie zastąpi wyszukiwarki internetowej.

Aby móc z powodzeniem wyszukiwać informacje, musisz najpierw wiedzieć, o co chcesz zapytać. Może to być z początku frustrujące, ale pomyśl o tym jak o grze w dwadzieścia pytań. Udoskonalaj swoje słowa kluczowe wraz każdym kolejnym wyszukiwaniem, aż znajdziesz konkretną odpowiedź lub osiągniesz punkt malejących zysków.

Jeśli poszukiwania w książkach i w sieci zawiodą, to kolejnym krokiem będzie poproszenie kogoś o pomoc. Możesz to zrobić online za opłatą lub za darmo na takich forach jak Stack Overflow (https://stackoverflow.com/). Pamiętaj jednak, że członkowie tych stron nie znoszą głupców. Zanim coś napiszesz, upewnij się, że zapoznałeś się z ich stronami „Jak należy zadawać pytania?”. Jedną z takich stron w witrynie Stack Overflow możesz przykładowo znaleźć pod adresem http://stackoverflow.com/help/how-to-ask/.

Naprzód!

Dziękuję, że poświęciłeś czas na przeczytanie tego wprowadzenia! Z pewnością chcesz wyciągnąć z tej książki tak wiele, jak to tylko możliwe, i jest to dobry początek. Gdy dojdziesz do drugiego końca tej książki, będziesz bardziej biegły w Pythonie i lepiej przygotowany do rozwiązywania złożonych rzeczywistych problemów. Ruszajmy do pracy.

1

Generator zabawnych pseudonimów

Swego czasu na kanale telewizyjnym USA Network emitowany był komediodramat detektywistyczny zatytułowany Psych[1], w którym obdarzony niesamowitą spostrzegawczością szpieg amator Sean rozwiązywał kolejne sprawy, udając przy tym medium. Znakiem firmowym serialu był sposób, w jaki Sean przedstawiał swojego pomocnika Gusa, posługując się wymyślanymi na poczekaniu

zabawnymi pseudonimami, takimi jak Galileo Humpkins, Lavender Gooms czy Bad News Marvin Barnes. Wywarło to na mnie wrażenie, ponieważ przed laty jeden z pracowników agencji Census Bureau[2] dał mi listę prawdziwych nazwisk, które były tak samo dziwne, jak te wymyślane przez Seana.

Projekt 1: Generowanie pseudonimów

W ramach tego projektu, w formie rozgrzewki, napiszemy prosty program w Pythonie do generowania zwariowanych nazw poprzez losowe łączenie ze sobą imion i nazwisk. Przy odrobinie szczęścia uda nam się wygenerować szereg aliasów, z których niejeden pomocnik byłby dumny. Powtórzymy również najlepsze praktyki kodowania i wykorzystamy zewnętrzne programy, które pomogą nam pisać kod spełniający te wytyczne.

Jeśli nie darzysz sympatią serialu Psych, możesz zastąpić nazwy z mojej listy w kodzie, używając własnych żartów lub motywu przewodniego. Z łatwością możemy zmienić ten projekt w generator imion z serialu Gra o tron, bądź też odkryć prywatne nazwisko „Benedicta Cumberbatcha”. Moim ulubionym jest Bendylick Cricketbat.

Cel

Losowe generowanie śmiesznych imion i nazwisk dla pomocników za pomocą kodu w Pythonie, który jest zgodny z przyjętym stylem kodowania.

Planowanie i tworzenie projektu

Czas poświęcony na planowanie nigdy nie jest czasem straconym. Nie ma znaczenia, czy programujemy dla zabawy, czy dla zysku – w pewnym momencie będziemy musieli oszacować (dosyć dokładnie), jak długo zajmie nam tworzenie danego projektu, jakie przeszkody możemy napotkać, oraz jakie narzędzia i zasoby będą nam potrzebne do wykonania tej pracy. Abyśmy jednak byli w stanie to zrobić, musimy najpierw wiedzieć, co tak naprawdę chcemy stworzyć!

Pewien odnoszący sukcesy menedżer powiedział mi kiedyś, że jego sekretem jest po prostu zadawanie mnóstwa pytań: Co próbujesz zrobić? Dlaczego to robisz? Dlaczego robisz to w ten sposób? Ile masz czasu? Ile masz pieniędzy? Odpowiadanie na te pytania jest bardzo pomocne w procesie projektowania i daje nam czyste pole widzenia.

W swojej książce Myśl w języku Python! Nauka programowania[3], Allen Downey opisuje dwa rodzaje planów projektowania przy tworzeniu oprogramowania: „prototyp i poprawki” oraz „projektowane programowanie”. W przypadku prototypu i poprawek rozpoczynamy od prostego programu, a następnie za pomocą poprawek (wyedytowanego kodu) obsługujemy problemy napotkane podczas testowania. Podejście to może być przydatne, gdy staramy się rozwiązać złożony problem, którego nie rozumiemy zbyt dobrze. Może ono jednak również wytwarzać skomplikowany i zawodny kod. Jeśli dobrze rozumiemy problem i znamy sposób jego rozwiązania, powinniśmy posłużyć się planem zaprojektowanego programowania, aby uniknąć przyszłych problemów i ich późniejszych poprawek. Podejście to może sprawić, że kodowanie będzie łatwiejsze i bardziej wydajne, a do tego zwykle prowadzi ono do trwalszego i bardziej solidnego kodu.

Wszystkie projekty w tej książce rozpoczynać będziemy od jasno zdefiniowanego problemu lub celu, który będzie podstawą do naszych decyzji projektowych. Następnie omawiać będziemy strategię w celu lepszego zrozumienia problemów i utworzenia planu projektowanego programowania.

Strategia

Rozpoczniemy od dwóch list, first i last, które przechowywać będą śmieszne imiona i nazwiska. Listy te będą względnie krótkie, więc nie będą one wymagać dużej ilości pamięci, nie będą musiały być dynamicznie aktualizowane i nie powinny stwarzać żadnych problemów w czasie działania. Ponieważ będziemy jedynie odczytywać nazwy zawarte w tych listach, jako kontener wykorzystamy krotkę.

Mając zdefiniowane dwie krotki z imionami i nazwiskami, za dotknięciem klawisza będziemy generować nowe nazwy, łącząc w pary imiona i nazwiska. W ten sposób użytkownik będzie mógł łatwo powtarzać ten proces, aż do uzyskania wystarczająco śmiesznego wyniku.

Powinniśmy również w jakiś sposób uwydatnić to imię i nazwisko w oknie interpretatora, tak aby wyróżniało się ona na tle innych poleceń. Powłoka IDLE nie dostarcza zbyt wielu opcji związanych z czcionką, ale jak wiemy – i to nazbyt dobrze – błędy oznaczane są kolorem czerwonym. Domyślnie funkcja print() wypisuje informacje na standardowe wyjście, ale po załadowaniu modułu sys możemy przekierować wyjście na standardowy kanał błędów (wraz z jego charakterystyczną czerwoną kolorystyką) za pomocą parametru file: print(coś, file=sys.stderr).

Na koniec ustalimy, jakie rekomendacje dotyczące stylu kodowania istnieją dla programowania w Pythonie. Wytyczne te powinny dotyczyć nie tylko samego kodu, ale także dokumentacji zagnieżdżonej w obrębie tego kodu.

Pseudokod

„Na Amerykanów zawsze można liczyć, że jak już wyczerpią wszystkie złe rozwiązania, wreszcie zastosują właściwe”. Cytat ten, luźno wiązany z Winstonem Churchillem, podsumowuje sposób, w jaki wiele osób podchodzi do pisania pseudokodu.

Pseudokod jest ogólnym, nieformalnym sposobem opisywania programów komputerowych za pomocą ustrukturyzowanego języka – angielskiego lub dowolnego innego języka ludzkiego. Powinien on przypominać uproszczony język programowania i zawierać słowa kluczowe oraz odpowiednie wcięcia. Dzięki niemu deweloperzy mogą pominąć całą nieprzeniknioną składnię prawdziwych języków programowania i skupić się na podstawowej logice. Mimo że jest on używany na szeroką skalę, pseudokod nie ma żadnego oficjalnego standardu, a jedynie wytyczne.

Jeśli w pewnym momencie poczujemy się sfrustrowani, to może być to spowodowane tym, że nie poświęciliśmy czasu na napisanie pseudokodu. Głęboko w to wierzę, ponieważ pseudokod zawsze – bez wyjątków – prowadził mnie w kierunku rozwiązań, gdy przed jego napisaniem nie mogłem sobie z czymś poradzić. Z tego względu w większości projektów w tej książce używać będziemy pewnego rodzaju pseudokodu. Mam nadzieję, że dostrzeżesz jego użyteczność, ale liczę również na to, że zdyscyplinujesz się do pisania go w swoich własnych projektach.

Bardzo ogólny pseudokod dla naszego generatora śmiesznych pseudonimów może wyglądać tak:

Wczytaj listę imion

Wczytaj listę nazwisk

Wybierz losowo imię

Przypisz to imię do zmiennej

Wybierz losowo nazwisko

Przypisz to nazwisko do zmiennej

Wypisz te nazwy na ekranie w odpowiedniej kolejności i w kolorze czerwonym

Zapytaj użytkownika, czy chce grać dalej

Jeśli użytkownik gra dalej:

powtórz

Jeśli użytkownik chce zakończyć

zakończ i zamknij program

Jeśli nie staramy się zaliczyć jakiegoś kursu programowania lub dostarczyć jasnych instrukcji innym osobom, powinniśmy się skupić na celu tego pseudokodu i nie zawracać sobie głowy niewolniczym stosowaniem się do (nieustandaryzowanych) wytycznych dotyczących jego pisania. Nie poprzestawajmy również na samym programowaniu – proces pisania pseudokodu możemy stosować do wielu innych rzeczy. Gdy już się do niego przyzwyczaimy, zauważymy, że pomaga nam on realizować inne zadania, takie jak obliczanie podatków, planowanie inwestycji, budowanie domu czy przygotowywanie wyjazdu na kemping. Jest to świetny sposób na zebranie myśli i przeniesienie sukcesów z programowania do prawdziwego życia.

Kod

Listing 1.1 zawiera kod generatora pseudonimów, pseudonyms.py, który kompiluje się i wypisuje ich listę z dwóch krotek zawierających imiona i nazwiska. Jeśli nie chcesz wpisywać wszystkich nazw, możesz wpisać ich podzbiór lub pobrać ten kod w całości ze strony https://nostarch.com/impracticalpython/.

pseudonyms.py

import sys, random

print("Welcome to the Psych 'Sidekick Name Picker.'\n")

print("A name just like Sean would pick for Gus:\n\n")

first = ('Baby Oil', 'Bad News', 'Big Burps', "Bill 'Beenie-Weenie'",

"Bob 'Stinkbug'", 'Bowel Noises', 'Boxelder', "Bud 'Lite' ",

'Butterbean', 'Buttermilk', 'Buttocks', 'Chad', 'Chesterfield',

'Chewy', 'Chigger", "Cinnabuns', 'Cleet', 'Cornbread', 'Crab Meat',

'Crapps', 'Dark Skies', 'Dennis Clawhammer', 'Dicman', 'Elphonso',

'Fancypants', 'Figgs', 'Foncy', 'Gootsy', 'Greasy Jim', 'Huckleberry',

'Huggy', 'Ignatious', 'Jimbo', "Joe 'Pottin Soil'", 'Johnny',

'Lemongrass', 'Lil Debil', 'Longbranch', '"Lunch Money"',

'Mergatroid', '"Mr Peabody"', 'Oil-Can', 'Oinks', 'Old Scratch',

'Ovaltine', 'Pennywhistle', 'Pitchfork Ben', 'Potato Bug',

'Pushmeet','Rock Candy', 'Schlomo', 'Scratchensniff', 'Scut',

"Sid 'The Squirts'", 'Skidmark', 'Slaps', 'Snakes', 'Snoobs',

'Snorki', 'Soupcan Sam', 'Spitzitout', 'Squids', 'Stinky',

'Storyboard', 'Sweet Tea', 'TeeTee', 'Wheezy Joe',

"Winston 'Jazz Hands'", 'Worms')

last = ('Appleyard', 'Bigmeat', 'Bloominshine', 'Boogerbottom',

'Breedslovetrout', 'Butterbaugh', 'Clovenhoof', 'Clutterbuck',

'Cocktoasten', 'Endicott', 'Fewhairs', 'Gooberdapple', 'Goodensmith',

'Goodpasture', 'Guster', 'Henderson', 'Hooperbag', 'Hoosenater',

'Hootkins', 'Jefferson', 'Jenkins', 'Jingley-Schmidt', 'Johnson',

'Kingfish', 'Listenbee', "M'Bembo", 'McFadden', 'Moonshine', 'Nettles',

'Noseworthy', 'Olivetti', 'Outerbridge', 'Overpeck', 'Overturf',

'Oxhandler', 'Pealike', 'Pennywhistle', 'Peterson', 'Pieplow',

'Pinkerton', 'Porkins', 'Putney', 'Quakenbush', 'Rainwater',

'Rosenthal', 'Rubbins', 'Sackrider', 'Snuggleshine', 'Splern',

'Stevens', 'Stroganoff', 'Sugar-Gold', 'Swackhamer', 'Tippins',

'Turnipseed', 'Vinaigrette', 'Walkingstick', 'Wallbanger', 'Weewax',

'Weiners', 'Whipkey', 'Wigglesworth', 'Wimplesnatch', 'Winterkorn',

'Woolysocks')

while True:

firstName = random.choice(first)

lastName = random.choice(last)

print("\n\n")

print("{} {}".format(firstName, lastName), file=sys.stderr)

print("\n\n")

try_again = input("\n\nTry again? (Press Enter else n to quit)\n ")

if try_again.lower() == "n":

break

input("\nPress Enter to exit.")

Listing 1.1. Generowanie śmiesznych pseudonimów na podstawie krotek z nazwami

Najpierw importujemy moduły sys i random . Modułu sys użyjemy w celu uzyskania dostępu do funkcjonalności związanej z komunikatami o błędach konkretnego systemu, dzięki czemu będziemy mogli pokolorować nasze wyjście w oknie IDLE na przykuwający uwagę kolor czerwony. Z kolei moduł random pozwoli nam wybierać w sposób losowy elementy z naszych list z imionami i nazwiskami.

Instrukcje print w punkcie przedstawiają program użytkownikowi. Polecenie \n wymusza przejście do nowego wiersza, natomiast znaki pojedynczego cudzysłowu '' pozwalają nam używać cudzysłowu w wydruku bez konieczności stosowania znaku ucieczki (ukośnik wsteczny), który znacząco by pogorszył czytelność kodu.

Następnie definiujemy nasze krotki z imionami i nazwiskami, po czym inicjujemy pętlę while . Ustawienie zmiennej while = True oznacza po prostu „wykonuj, dopóki nie powiem, kiedy przestać”. Ostatecznie użyjemy instrukcji break, aby zakończyć działanie pętli.

Pętla rozpoczyna się od losowego wyboru imienia z krotki first, po czym następuje przypisanie tego imienia do zmiennej firstName . W celu zwrócenia losowego elementu z niepustego ciągu – w tym wypadku krotki z imionami – wykorzystujemy metodę choice z modułu random.

Następnie wybieramy losowo nazwisko z krotki last i przypisujemy je do zmiennej lastName . Gdy mamy już oba te elementy, wypisujemy je i poprzez dostarczenie opcjonalnego argumentu file=sys.stderr do instrukcji print nakłaniamy interpreter IDLE do użycia czerwonej czcionki dla błędów. Do konwersji zmiennych przechowujących imię i nazwisko na ciągi znakowe użyjemy nowszej metody formatowania ciągów znaków zamiast starszego operatora formatowania ciągów znaków (%). Więcej informacji na temat tej nowej metody można znaleźć pod adresem https://docs.python.org/3.7/library/string.html.

Po wyświetleniu nazwy pytamy użytkownika, czy chce zagrać jeszcze raz, czy zakończyć. Używamy do tego funkcji input(), w ramach której podajemy instrukcję w cudzysłowie. W tym przypadku, aby zapewnić lepszą czytelność śmiesznych pseudonimów w oknie interpretera IDLE, wstawiamy dodatkowo kilka pustych wierszy. Jeśli użytkownik odpowie, wciskając klawisz enter, nic nie zostanie zwrócone do zmiennej try_again . Wówczas warunek w instrukcji if nie zostanie spełniony, pętla while będzie kontynuować swoje działanie i zostanie wyświetlona nowa nazwa. Jeśli zamiast tego użytkownik wciśnie klawisz N, wówczas instrukcja if spowoduje wykonanie polecenia break, przez co pętla zakończy się, ponieważ instrukcja while nie będzie już dłużej wyznaczać wartości True. Aby wyeliminować potencjalny wpływ klawisza capslock gracza, możemy posłużyć się metodą .lower(), która zamienia wszystkie znaki w ciągu na małe litery. Innymi słowy, nie ma znaczenia, czy użytkownik wprowadza dużą, czy małą literę N, ponieważ program zawsze będzie odczytywał ją jako małą.

Na koniec prosimy użytkownika o wyjście za pomocą klawisza enter . Wciśnięcie klawisza enter nie przypisuje do zmiennej wartości zwracanej przez funkcję input(), program kończy działanie, a okno konsoli zostaje zamknięte. Wciśnięcie klawisza f5 w oknie edytora IDLE wykonuje ukończony program.

Powyższy kod działa, ale samo działanie to zbyt mało – programy w języku Python powinny działać w odpowiednim stylu.

Korzystanie z przewodnika po stylach tworzonego przez społeczność Pythona

Zgodnie z jedną z wytycznych zawartych w PEP 20, „Zen of Python” (https://www.python.org/dev/peps/pep-0020/), „powinien istnieć pewien – a najlepiej tylko jeden – oczywisty sposób wykonania czegoś”. W duchu dostarczania jednego oczywistego „właściwego sposobu” wykonywania rzeczy i budowania konsensusu wokół tych praktyk, społeczność języka Python wydaje propozycje zmian lub rozszerzeń dla języka Python (Python Enhancement Proposal, PEP), które są konwencjami kodowania dla kodu Pythona tworzącego standardową bibliotekę w głównej dystrybucji Pythona. Najważniejszą z tych konwencji jest PEP 8, będąca przewodnikiem po stylach programowania w Pythonie. PEP 8 stale ewoluuje, w miarę jak określane są nowe konwencje, a stare wycofywane są z powodu zmian w języku.

PEP 8 (https://www.python.org/dev/peps/pep-0008/) wyznacza standardy w zakresie konwencji nazewnictwa, używania pustych wierszy, tabulatorów i spacji, maksymalnej długości wiersza, komentarzy itd. Propozycje te mają na celu podnieść czytelność kodu i sprawić, że będzie on spójny w ramach szerokiego spektrum programów pisanych w Pythonie. Osoby uczące się programowania powinny starać się przyswoić i stosować przyjęte konwencje, zanim złe nawyki zakorzenią się na dobre. Kod w tej książce będzie spełniać wytyczne PEP 8, przy czym niektóre z konwencji zostały zmienione (przykładowo poprzez użycie mniejszej ilości komentarzy, mniejszej liczby pustych wierszy oraz krótszych ciągów docstring) z szacunku do branży wydawniczej.

Ustandaryzowane nazwy i procedury są ważne zwłaszcza w przypadku pracy w zespołach wielofunkcyjnych. Wiele informacji może zostać utraconych w procesie tłumaczenia pomiędzy naukowcami i inżynierami, jak miało to miejsce w 1999 roku, kiedy to inżynierowie stracili sondę Mars Climate Orbiter, ponieważ różne zespoły używały różnych jednostek pomiarowych. Przez niemal dwie dekady budowałem komputerowe modele Ziemi, które były wykorzystywane w zastosowaniach inżynierskich. Inżynierowie używali skryptów do wczytywania tych modeli do ich własnego oprogramowania. W celu zwiększenia wydajności i zapewnienia pomocy osobom mniej doświadczonym udostępniali oni te skrypty między projektami. Ponieważ te „pliki poleceń” były dostosowywane do każdego projektu, inżynierowie z oczywistych powodów denerwowali się, gdy nazwy atrybutów zmieniały się podczas aktualizacji modelu. W zasadzie jednym z ich wewnętrznych wytycznych było „Błagaj, przekup lub zastrasz swojego twórcę modelu, aby używał spójnych nazw właściwości!”.

Sprawdzanie kodu za pomocą narzędzia Pylint

Powinniśmy zaznajomić się z wytycznymi PEP 8, ale wciąż będziemy popełniać błędy, a porównywanie naszego kodu z przewodnikiem będzie nas mocno opóźniać. Na szczęście programy takie jak Pylint, pycodestyle i Flake8 mogą pomóc nam w łatwy sposób podążać za rekomendacjami PEP 8 dotyczącymi stylów. Na potrzeby tego projektu skorzystamy z narzędzia Pylint.

Instalowanie narzędzia Pylint

Pylint jest narzędziem do sprawdzania kodu źródłowego, błędów i jakości kodu w języku Python. Aby pobrać jego darmową kopię, należy przejść na stronę https://www.pylint.org/#install i znaleźć przycisk instalacji dla swojej platformy. Przycisk ten ukaże polecenia do instalacji narzędzia Pylint. Na przykład w systemie Windows przechodzimy do folderu zawierającego kopię języka Python (np. C:\Python35), otwieramy menu kontekstowe za pomocą kombinacji SHIFT + prawy przycisk myszy, a następnie wybieramy opcję open command window here (Otwórz tutaj okno polecenia) lub open PowerShell window here (Otwórz tutaj okno programu PowerShell), w zależności od tego, z jakiej wersji systemu Windows korzystamy. W otwartym oknie wpisujemy pip install pylint.

Uruchamianie narzędzia Pylint

W systemie Windows narzędzie Pylint uruchamianie jest z poziomu okna wiersza polecenia, a w przypadku nowszych systemów – z okna programu PowerShell (oba te okna można otworzyć za pomocą kombinacji shift + prawy przycisk myszy, użytej w folderze zawierającym moduł Pythona, który chcemy sprawdzić). Aby uruchomić ten program, należy wpisać polecenie pylint nazwapliku (patrz rys. 1.1). Rozszerzenie .py jest opcjonalne, zaś ścieżka do katalogu może się różnić od tej widocznej na rysunku. W przypadku systemu macOS lub innego systemu opartego na systemie Unix należy posłużyć się emulatorem terminala.

Rysunek 1.1. Okno wiersza polecenia systemu Windows z poleceniem uruchamiającym narzędzie Pylint

Okno wiersza polecenia wyświetli rezultaty działania narzędzia Pylint. Oto przykład przydatnego wyniku:

C:\Python35\Python 3 Stuff\Psych>pylint pseudonyms.py

No config file found, using default configuration

************* Module pseudonyms

C: 45, 0: No space allowed around keyword argument assignment

print(firstName, lastName, file = sys.stderr)

^ (bad-whitespace)

C: 1, 0: Missing module docstring (missing-docstring)

C: 2, 0: Multiple imports on one line (sys, random) (multiple-imports)

C: 7, 0: Invalid constant name "first" (invalid-name)

C: 23, 0: Invalid constant name "last" (invalid-name)

C: 40, 4: Invalid constant name "firstName" (invalid-name)

C: 42, 4: Invalid constant name "lastName" (invalid-name)

C: 48, 4: Invalid constant name "try_again" (invalid-name)

Wielka litera na początku każdego wiersza jest kodem komunikatu. Przykładowo kod C: 15, 0 odnosi się do naruszenia standardu kodowania w wierszu 15, kolumnie 0. Poszczególne kody komunikatów narzędzia Pylint można odczytać za pomocą poniższego klucza:

R Refaktoryzuj z powodu naruszenia metryki „dobrej praktyki”

C Konwencja dotycząca naruszenia standardu kodowania

W Ostrzeżenie przed problemami stylistycznymi lub pomniejszymi problemami programistycznymi

E Błąd dotyczący istotnych problemów programistycznych (tj. najprawdopodobniej jakiś błąd w kodzie)

F Błąd krytyczny, który uniemożliwia dalsze przetwarzanie

Pylint zakończy swój raport, przyznając naszemu programowi ocenę zgodności z PEP 8. W naszym przykładzie kod otrzymał ocenę 4 na 10:

Global evaluation

-----------------

Your code has been rated at 4.00/10 (previous run: 4.00/10, +0.00)

Obsługiwanie fałszywych błędów dotyczących nazw stałych

Jak można zauważyć, Pylint niepoprawnie zakłada, że wszystkie nazwy zmiennych w przestrzeni globalnej odnoszą się do stałych, a tym samym powinny być pisane wielkimi literami. Mankament ten możemy rozwiązać na kilka sposobów. Pierwszym z nich jest zagnieżdżenie naszego kodu w funkcji main(), jak to pokazano na listingu 1.2, dzięki czemu nie będzie się on znajdował w przestrzeni globalnej.

def main():

jakiś wcięty kod

jakiś wcięty kod

jakiś wcięty kod

if __name__ == "__main__":

main()

Listing 1.2. Definicja i wywołanie funkcji main()

Zmienna __name__ jest specjalną wbudowaną zmienną, za pomocą której możemy sprawdzić, czy program uruchamiany jest w trybie samodzielnym, czy jako moduł zaimportowany. Pamiętajmy, że moduł jest po prostu programem w Pythonie, używanym wewnątrz innego programu. Jeśli uruchomimy program bezpośrednio, wówczas zmienna __name__ ustawiona zostanie na wartość __main__. Na listingu 1.2 użyto zmiennej __name__, aby zagwarantować, że po zaimportowaniu programu funkcja main() nie zostanie uruchomiona, dopóki sami jej jawnie nie wywołamy . Gdy jednak program zostanie uruchomiony bezpośrednio, warunek w instrukcji if zostanie spełniony i funkcja main() zostanie wywołana automatycznie . Nie zawsze musimy korzystać z tej konwencji. Przykładowo, jeśli nasz kod definiuje po prostu jakąś funkcję, możemy wczytać ją jako moduł i wywołać bez potrzeby używania zmiennej __name__.

Wszystko z wyjątkiem instrukcji import umieścimy w funkcji main(), w pliku pseudonyms.py, a wywołanie funkcji main() umieścimy w instrukcji if, jak na listingu 1.2. Możesz wprowadzić te zmiany samodzielnie lub pobrać gotowy program pseudonyms_main.py z witryny tej książki. Uruchamiamy ponownie narzędzie Pylint. W oknie polecenia powinniśmy otrzymać następujące wyniki:

C:\Python35\Python 3 Stuff\Psych>pylint pseudonyms_main

No config file found, using default configuration

************* Module pseudonyms_main

C: 47, 0: No space allowed around keyword argument assignment

print(firstName, lastName, file = sys.stderr)

^ (bad-whitespace)

C: 1, 0: Missing module docstring (missing-docstring)

C: 2, 0: Multiple imports on one line (sys, random) (multiple-imports)

C: 4, 0: Missing function docstring (missing-docstring)

C: 42, 8: Invalid variable name "firstName" (invalid-name)

C: 44, 8: Invalid variable name "lastName" (invalid-name)

Teraz te denerwujące komentarze odnośnie nieprawidłowych nazw stałych zniknęły, ale to jeszcze nie koniec. Choć bardzo lubię nazwy w notacji camelCase, jak na przykład firstName, jednak konwencje Pythona nie pozwalają na jej stosowanie.

Konfigurowanie narzędzia Pylint

W przypadku oceniania prostych skryptów wolę używać domyślnych ustawień narzędzia Pylint i ignorować fałszywe błędy dotyczące nazw stałych. Lubię również korzystać z opcji -rn (skrót dla -reports=n), aby wyłączać wyświetlanie obszernych ilości statystyk, które są zwracane przez Pylint:

C:\Python35\Python 3 Stuff\Psych>pylint -rn pseudonyms_main.py

Zwróćmy uwagę, że użycie opcji -rn wyłączy opcję oceny kodu.

Kolejnym problemem z narzędziem Pylint jest to, że jego maksymalna długość wiersza wynosi domyślnie 100 znaków, ale PEP 8 zaleca 79 znaków. Aby dostosować się do wytycznych PEP 8, można uruchomić Pylint z następującą opcją:

C:\Python35\Python 3 Stuff\Psych>pylint --max-line-length=79 pseudonyms_main

Teraz zobaczymy, że wstawienie wcięć dla imion i nazwisk w funkcji main() spowodowało, iż niektóre wiersze przekroczyły zalecaną długość:

C: 12, 0: Line too long (80/79) (line-too-long)

C: 14, 0: Line too long (83/79) (line-too-long)

--wycinek—-

Raczej nie będziemy chcieli konfigurować narzędzia Pylint przy każdym uruchomieniu i na szczęście nie musimy tego robić. Zamiast tego możemy za pomocą polecenia --generate-rcfile utworzyć nasz własny niestandardowy plik konfiguracyjny. Przykładowo, aby zawiesić raportowanie i ustawić maksymalną długość wiersza na 79 znaków, należy w wierszu polecenia wprowadzić poniższe polecenie:

twoja ścieżka>pylint -rn --max-line-length=79 --generate-rcfile > nazwa.pylintrc

Wszelkie opcje, które chcemy wprowadzić, umieszczamy przed instrukcją --generate-rcfile > nazwa.pylintrc, wpisując naszą własną nazwę przed rozszerzeniem .pylintrc. Plik konfiguracji możemy utworzyć samodzielnie, jak to pokazaliśmy, albo też w czasie oceniania programu w Pythonie. Plik .pylintrc jest automatycznie zapisywany w naszym bieżącym katalogu roboczym, przy czym istnieje opcja pozwalająca na dodanie ścieżki do katalogu (więcej informacji na ten temat można znaleźć na stronach https://pylint.org oraz https://pylint.readthedocs.io/en/latest/user_guide/run.html).

Aby wykorzystać ponownie nasz niestandardowy plik konfiguracji, używamy opcji --rcfile, po której podajemy nazwę tego pliku i nazwę programu, który oceniamy. Przykładowo, aby użyć pliku myconfig.pylintrc dla programu pseudonyms_main.py, należy użyć polecenia:

C:\Python35\Python 3 Stuff\Psych>pylint --rcfile myconfig.pylintrc pseudonyms_main

Opisywanie kodu za pomocą ciągów docstring

Pylint wskazuje, że w programie pseudonyms_main.py brakuje ciągu dokumentacyjnego docstring. Zgodnie z przewodnikiem po stylach PEP 257 (https://www.python.org/dev/peps/pep-0257/), ciąg dokumentacyjny docstring jest literałem znakowym, występującym jako pierwsza instrukcja w definicji modułu, funkcji, klasy lub metody. Ciąg docstring jest po prostu krótkim opisem tego, co robi nasz kod, i może zawierać szczegóły na temat różnych aspektów kodu, takich jak na przykład wymagane przez niego dane. Poniżej, w potrójnych znakach cudzysłowu, znajduje się przykład pojedynczego ciągu docstring dla funkcji:

def circ(r):

"""Return the circumference of a circle with radius of r."""

c = 2 * r * math.pi

return c

Powyższy ciąg docstring określa, co dana funkcja robi, ale ciągi docstring mogą być dłuższe i zawierać więcej informacji. Na przykład poniżej znajduje się wielowierszowy ciąg docstring dla tej samej funkcji, który wyświetla informacje dotyczące danych i wartości wyjściowych tej funkcji:

def circ(r):

"""Return the circumference of a circle with radius of r.

Arguments:

r – radius of circle

Returns:

float: circumference of circle

"""

c = 2 * r * math.pi

return c

Niestety ciągi docstring zależą od konkretnej osoby, projektu i firmy, tak więc istnieje dla nich wiele zaleceń, które stoją ze sobą w sprzeczności. Google ma swój własny format oraz świetny przewodnik. Niektórzy członkowie społeczności naukowej stosują standard docstring o nazwie NumPy. Również reStructuredText jest popularnym formatem, używanym głównie w połączeniu z narzędziem Sphinx, które wykorzystuje ciągi docstring do generowania dokumentacji dla projektów w Pythonie w formatach HTML i PDF. Ktoś, kto kiedykolwiek czytał dokumentację (https://readthedocs.org/) dla jakiegoś modułu Python, widział narzędzie Sphinx w akcji. Łącza prowadzące do wytycznych dla niektórych z tych różnych stylów znajdują się w części „Materiały dodatkowe”, na stronie 15.

Aby sprawdzić, w jakim stopniu nasze ciągi docstring spełniają wymagania konwencji PEP 257, możemy posłużyć się darmowym narzędziem o nazwie pydocstyle. Aby zainstalować je w systemie Windows lub dowolnym innym systemie operacyjnym, należy otworzyć okno wiersza polecenia i wpisać pip install pydocstyle (jeśli Python zainstalowany jest zarówno w wersji 2, jak i wersji 3, to należy użyć narzędzia pip3).

Aby uruchomić narzędzie pydocstyle, otwieramy wiersz polecenia w folderze zawierającym kod, który chcemy sprawdzić. Jeśli nie podamy nazwy pliku, pydocstyle zostanie uruchomiony dla wszystkich programów w Pythonie dostępnych w tym folderze i otrzymamy taki wynik:

C:\Python35\Python 3 Stuff\Psych>pydocstyle

.\OLD_pseudonyms_main.py:1 at module level:

D100: Missing docstring in public module

.\OLD_pseudonyms_main.py:4 in public function `main`:

D103: Missing docstring in public function

.\ pseudonyms.py:1 at module level:

D100: Missing docstring in public module

.\ pseudonyms_main_broken.py:1 at module level:

D200: One-line docstring should fit on one line with quotes (found 2)

.\ pseudonyms_main_broken.py:6 in public function `main`:

D205: 1 blank line required between summary line and description

(found 0)

Jeśli podamy plik, w którym nie ma żadnych problemów z ciągami docstring, pydocstyle nie zwróci nam niczego:

C:\Python35\Python 3 Stuff\Psych>pydocstyle pseudonyms_main_fixed.py

C:\Python35\Python 3 Stuff\Psych>

We wszystkich projektach w tej książce używać będziemy stosunkowo prostych ciągów docstring, aby zredukować w ten sposób wizualny szum w opatrzonym opisem kodzie. Jeśli chcesz, możesz je bez przeszkód rozbudowywać, aby je w ten sposób przećwiczyć. Uzyskane rezultaty zawsze można sprawdzić za pomocą narzędzia pydocstyle.

Sprawdzanie stylu naszego kodu

Gdy dorastałem, mój wujek dojeżdżał z naszego miasteczka do większego miasta, aby miejscowy fryzjer „wystylizował” jego włosy. Nigdy nie rozumiałem, czym różni się to od zwykłego strzyżenia, ale wiem natomiast, w jaki sposób „wystylizować” kod naszego generatora śmiesznych pseudonimów, tak aby spełniał on wymagania PEP 8 i PEP 257.

Tworzymy kopię pliku pseudonyms_main.py o nazwie pseudonyms_main_fixed.py i natychmiast oceniamy ją za pomocą narzędzia Pylint przy użyciu tego polecenia:

Twoja ścieżka>pylint --max-line-length=79 pseudonyms_main_fixed

Nie ukrywamy raportu za pomocą opcji -rn. Na dole okna polecenia powinniśmy zobaczyć poniższy wynik:

Global evaluation

----------------

Your code has been rated at 3.33/1

Teraz poprawiamy kod w oparciu o wynik Pylint. W poniższym przykładzie wytłuściłem wszystkie poprawki. Wprowadziłem zmiany do krotek z nazwami, aby rozwiązać w ten sposób problemy z długością wierszy. Poprawiony kod jest również dostępny do pobrania w formie pliku pseudonyms_main_fixed.py ze strony https://www.nostarch.com/impracticalpython/.

pseudonyms_main_fixed.py

"""Generate funny names by randomly combining names from 2 separate lists."""

import sys

import random

def main():

"""Choose names at random from 2 tuples of names and print to screen."""

print("Welcome to the Psych 'Sidekick Name Picker.'\n")

print("A name just like Sean would pick for Gus:\n\n")

first = ('Baby Oil', 'Bad News', 'Big Burps', "Bill 'Beenie-Weenie'",

"Bob 'Stinkbug'", 'Bowel Noises', 'Boxelder', "Bud 'Lite'",

'Butterbean', 'Buttermilk', 'Buttocks', 'Chad', 'Chesterfield',

'Chewy', 'Chigger', 'Cinnabuns', 'Cleet', 'Cornbread',

'Crab Meat', 'Crapps', 'Dark Skies', 'Dennis Clawhammer',

'Dicman', 'Elphonso', 'Fancypants', 'Figgs', 'Foncy', 'Gootsy',

'Greasy Jim', 'Huckleberry', 'Huggy', 'Ignatious', 'Jimbo',

"Joe 'Pottin Soil'", 'Johnny', 'Lemongrass', 'Lil Debil',

'Longbranch', '"Lunch Money"', 'Mergatroid', '"Mr Peabody"',

'Oil-Can', 'Oinks', 'Old Scratch', 'Ovaltine', 'Pennywhistle',

'Pitchfork Ben', 'Potato Bug', 'Pushmeet', 'Rock Candy',

'Schlomo', 'Scratchensniff', 'Scut', "Sid 'The Squirts'",

'Skidmark', 'Slaps', 'Snakes', 'Snoobs', 'Snorki', 'Soupcan Sam',

'Spitzitout', 'Squids', 'Stinky', 'Storyboard', 'Sweet Tea',

'TeeTee', 'Wheezy Joe', "Winston 'Jazz Hands'", 'Worms')

last = ('Appleyard', 'Bigmeat', 'Bloominshine', 'Boogerbottom',

'Breedslovetrout', 'Butterbaugh', 'Clovenhoof', 'Clutterbuck',

'Cocktoasten', 'Endicott', 'Fewhairs', 'Gooberdapple',

'Goodensmith', 'Goodpasture', 'Guster', 'Henderson', 'Hooperbag',

'Hoosenater', 'Hootkins', 'Jefferson', 'Jenkins',

'Jingley-Schmidt', 'Johnson', 'Kingfish', 'Listenbee', "M'Bembo",

'McFadden', 'Moonshine', 'Nettles', 'Noseworthy', 'Olivetti',

'Outerbridge', 'Overpeck', 'Overturf', 'Oxhandler', 'Pealike',

'Pennywhistle', 'Peterson', 'Pieplow', 'Pinkerton', 'Porkins',

'Putney', 'Quakenbush', 'Rainwater', 'Rosenthal', 'Rubbins',

'Sackrider', 'Snuggleshine', 'Splern', 'Stevens', 'Stroganoff',

'Sugar-Gold', 'Swackhamer', 'Tippins', 'Turnipseed',

'Vinaigrette', 'Walkingstick', 'Wallbanger', 'Weewax', 'Weiners',

'Whipkey', 'Wigglesworth', 'Wimplesnatch', 'Winterkorn',

'Woolysocks')

while True:

first_name = random.choice(first)

last_name = random.choice(last)

print("\n\n")

# Oszukaj IDLE za pomocą ustawienia "krytycznego błędu", aby wypisać

# imię i nazwisko na czerwono.

print("{} {}".format(first_name, last_name), file=sys.stderr)

print("\n\n")

try_again = input("\n\nTry again? (Press Enter else n to quit)\n ")

if try_again.lower() == "n":

break

input("\nPress Enter to exit.")

if __name__ == "__main__":

main()

Pylint ocenił ten poprawiony kod na 10 punktów:

Global evaluation

----------------

Your code has been rated at 10.00/10 (previous run: 3.33/10, +6.67)

Jak zobaczyliśmy w poprzednim podrozdziale, uruchomienie narzędzia pydocstyle na pliku pseudonyms_main_fixed.py nie zgłasza żadnych błędów, ale nie myślmy, że oznacza to, iż wszystko jest poprawne lub nawet zadowalające. Przykładowo następujący ciąg znaków również przechodzi ten test: """ksjkdls lskjds kjs jdi wllk sijkljs dsdw noiu sss.""".

Trudno jest pisać krótkie, zwięzłe i naprawdę przydatne ciągi docstring i komentarze. PEP 257 pomoże nam z ciągami docstring, ale komentarze mają bardziej luźny styl i „otwarty zakres”. Zbyt duża ilość komentarzy tworzy wizualny szum i może zrażać użytkownika, a wiele z nich nie jest nawet potrzebnych, ponieważ dobrze napisany kod w dużej mierze dokumentuje się sam. Dobrym powodem do wstawienia komentarza może być chociażby chęć objaśnienia zamiaru i próba uniknięcia popełnienia błędu przez użytkownika, jak w przypadku, gdy wymagane są konkretne jednostki pomiarowe lub formaty danych. Aby znaleźć właściwą równowagę w komentowaniu kodu, zwracajmy uwagę na dobre przykłady, gdy będziemy je napotykać. Ponadto warto zadać sobie pytanie, co my sami chcielibyśmy zobaczyć, gdybyśmy otrzymali nasz własny kod po pięcioletniej przerwie!

Narzędzia Pylint i pydocstyle są w łatwe w instalacji, łatwe w uruchamianiu i pomogą nam zapoznać się ze standardami kodowania przyjętymi w społeczności języka Python i do nich dostosować. Gdy szukamy pomocy, przepuszczenie naszego kodu przez narzędzie Pylint przed opublikowaniem go na forum internetowym również jest uznawane za dobrą praktykę i może spowodować, że uzyskamy w ten sposób „bardziej uprzejme i łagodniejsze” odpowiedzi!

Podsumowanie

Teraz powinniśmy już wiedzieć, w jaki sposób pisać kod i dokumentację, które spełniają oczekiwania społeczności języka Python. Jednak, co bardziej istotne, wygenerowaliśmy szereg naprawdę zabawnych pseudonimów dla pomocnika, gangstera, informatora, czy kogokolwiek innego. Oto kilka z moich ulubionych:

Pitchfork Ben Pennywhistle
‘Bad News’ Bloominshine

Chewy Stroganoff
‘Sweet Tea’ Tippins

Spitzitout Winterkorn
Wheezy Joe Jenkins

‘Big Burps’ Rosenthal
Soupcan Sam Putney

Bill ‘Beenie-Weenie’ Clutterbuck
Greasy Jim Wigglesworth

Dark Skies Jingley-Schmidt
Chesterfield Walkingstick

Potato Bug Quakenbush
Jimbo Woolysocks

Worms Endicott
Fancypants Pinkerton

Cleet Weiners
Dicman Overpeck

Ignatious Outerbridge
Buttocks Rubbins

Materiały dodatkowe

Interaktywna wersja tych zasobów znajduje się na stronie https://www.nostarch.com/impracticalpython/.

Pseudokod

Opisy pewnych dosyć formalnych standardów związanych z pseudokodem dostępne są na stronach http://users.csc.calpoly.edu/~jdalbey/SWE/pdl_std.html oraz http://www.slideshare.net/sabiksabz/pseudo-code-basics/.

Przewodniki po stylach

Poniżej znajduje się lista przewodników po stylach, po które możemy sięgać podczas tworzenia programów w Pythonie.

- • Przewodnik PEP 8 można znaleźć pod adresem https://www.python.org/dev/peps/pep-0008/.

- • Wytyczne PEP 257 dostępne są na stronie https://www.python.org/dev/peps/pep-0257/.

- • Google ma swój własny przewodnik po stylach i formatach: https://google.github.io/styleguide/pyguide.html.

- • Przykłady stylu Google można znaleźć na stronie https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html.

- • Standardy dla ciągów docstring biblioteki NumPy znajdują się pod adresem https://numpydoc.readthedocs.io/en/latest/.

- • Przykłady ciągów docstring w formacie NumPy można znaleźć pod adresem https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html.

- • Więcej informacji na temat formatu reStructuredText można znaleźć na stronach https://docs.python.org/devguide/documenting.html, https://docs.python.org/3.1/documenting/rest.html oraz https://wiki.python.org/moin/reStructuredText/.

- • Podręcznik „The Hitchhiker’s Guide to Python” (http://docs.python-guide.org/en/latest/writing/style/) zawiera podrozdział poświęcony stylom kodowania i narzędziu autopep8, które automatycznie formatuje kod zgodnie z wytycznymi PEP 8 (do pewnego stopnia).

- • Książka „Efektywny Python. 59 sposobów na lepszy kod”[4] autorstwa Bretta Slatkina zawiera przydatny podrozdział poświęcony dokumentowaniu programów.

Moduły zewnętrzne

Poniżej znajdują się pewne zasoby wyjaśniające sposób korzystania z zewnętrznych modułów.

- • Szczegóły na temat modułu Pylint znajdują się na stronie https://docs.pylint.org/en/1.8/tutorial.html.

- • Szczegóły na temat narzędzia pydocstyle można znaleźć pod adresem http://www.pydocstyle.org/en/latest/.

Ćwiczenia

Spróbuj wykonać te projekty, aby przećwiczyć pracę z ciągami znaków. Moje własne rozwiązania dla tych projektów dostępne są w dodatku na końcu książki.

Świńska łacina

Aby utworzyć tzw. świńską łacinę, należy wybrać jakieś angielskie słowo rozpoczynające się od spółgłoski, przenieść tę spółgłoskę na jego koniec, a następnie dodać do niego końcówkę „ay”. Jeśli słowo rozpoczyna się od samogłoski, to na końcu słowa dodajemy końcówkę „way”. Jedną z najbardziej znanych fraz w świńskiej łacinie jest „ixnay on the ottenray”, wypowiedziane przez Martiego Feldmana w mistrzowskiej komedii Mela Brooksa pt. „Młody Frankenstein”.

Napisz program, który przyjmuje na wejściu słowo, a następnie przy wykorzystaniu indeksowania i wycinania zwraca odpowiednik tego słowa w świńskiej łacinie. Uruchom Pylint i pydocstyle na swoim kodzie i popraw wszelkie błędy w stylu. Rozwiązanie dla tego projektu znajduje się w dodatku na końcu tej książki. Jest ono również dostępne w pliku pig_latin_practice.py na stronie https://www.nostarch.com/impracticalpython/.

Wykres słupkowy dla języka angielskiego

Sześć najczęściej używanych liter w języku angielskim można zapamiętać przy użyciu skrótu mnemonicznego „etaoin”. Napisz skrypt w języku Python, który pobiera na wejściu zdanie (ciąg znaków) i zwraca prosty wykres słupkowy, widoczny na rysunku 1.2. Wskazówka: wykorzystałem tutaj strukturę danych słownika oraz dwa moduły, których jeszcze nie omawialiśmy: pprint oraz collections/defaultdict.

Rysunek 1.2. Wykres słupkowy wygenerowany przez program ETAOIN_practice.py zaprezentowany w dodatku tej książki

Wyzwania

Rozwiązania dla poniższych projektów nie są podane. Trzeba rozwiązać te problemy samodzielnie!

Wykres słupkowy dla języków romańskich

Przy użyciu translatora online zmień swój tekst na inny system zapisu oparty na łacinie (np. język hiszpański lub francuski), uruchom ponownie kod z projektu „Wykres słupkowy dla języka angielskiego” i porównaj uzyskane wyniki. Przykładowo hiszpańska wersja tekstu z rysunku 1.2 generuje wyniki pokazane na rysunku 1.3.

Rysunek 1.3. Wynik działania programu ETAOIN_challenge.py po wprowadzeniu na wejściu hiszpańskiego tłumaczenia tekstu z rysunku 1.2

W zdaniu w języku hiszpańskim jest dwa razy więcej liter L i trzy razy więcej liter U. Aby móc bezpośrednio porównać ze sobą wykresy słupkowe dla różnych danych, zmień kod w taki sposób, aby każda litera alfabetu miała swój klucz i była wyświetlana nawet wtedy, gdy nie istnieje dla niego żadna wartość.

Drugie imię

Przepisz kod generatora śmiesznych pseudonimów w taki sposób, aby uwzględniał drugie imiona. Najpierw utwórz nową krotkę middle_name, a następnie rozdziel istniejące pary „pierwsze imię-drugie imię” (takie jak „Joe ‘Pottin Soil’” lub „Sid ‘The Squirts’”) i dodaj je do tej krotki. Do krotki middle_name powinny zostać również przeniesione oczywiste ksywki (np. „Oil Can”). Na koniec dodaj jakieś nowe drugie imiona (takie jak „The Big News”, „Grunts” lub „Tinkie Winkie”). Użyj modułu random w taki sposób, aby drugie imię wybierane było tylko raz na dwie lub trzy próby.

Coś całkowicie innego

Utwórz swoją własną listę śmiesznych pseudonimów i dodaj ją do generatora. Wskazówka: tego rodzaju imiona można łatwo znaleźć w napisach końcowych filmów.

Przypisy

1 W Polsce serial był emitowany pod nazwą „Świry”. (przyp. tłum.)

2 United States Census Bureau jest amerykańską agencją statystyczną. (przyp. tłum.)

3 Allen B. Downey, „Think Python” 2nd Edition, (O’Reilly, 2015); wydanie polskie Helion, 2017.

4 Brett Slatkin, „Effective Python: 59 Specific Ways to Write Better Python” (Addison-Wesley, 2015).