Excel

Pro příklady z tohoto oddílu budete potřebovat vhodnou tabulku ve formátu v CSV. Tady můžete jednu stáhnout – jsou to data o školní docházce, stažená z webu UN Data. Problém s tou tabulkou je, že jako oddělovač je použitý středník, takže ji někdy Excel otevírá špatně. Brzy to opravím.

Příklad. Vyrobte novou tabulku, ve které budou jen počty školáků (tedy řádky s "Attending school" ve sloupci F).

Řešení. Myslím, že Python je v tomhle případě zbytečné používat: když máte tabulku otevřenou v Excelu, stačí ji seřadit podle sloupce F, vybrat řádky ke smazání pomocí Ctrl+Shift+End, smazat je a tabulku znovu setřídit podle země a roku.

Příklad. Vyrobte novou tabulku, která za každý stát bude obsahovat jen nejaktuálnější údaje. To znamená, za každý stát najděte nejnovější datum ve sloupci "Year" a vyberte jen řádky s touto hodnotou.

Řešení. # -*- encoding: utf8 -*- # otevřeme soubor a všechny řádky si načteme do seznamu f = open("school_attendance.csv", "r") rows = f.readlines() f.close() # připravíme si slovník na nejnovější rok každého státu latest = dict() # projdeme celou tabulku a každému státu nastavíme hodnotu for row in rows[1:]: country, year, garbage = row.split(";", 2) if country not in latest or latest[country] < int(year): latest[country] = int(year) # vyrobíme jiný soubor a otevřeme ho pro zápis f = open("vysledek.csv", "w+") # zapíšeme první řádek f.write(rows[0]) # cyklem projdeme všechny řádky vyjma prvního for row in rows[1:]: country, year, garbage = row.split(";", 2) # zapíšeme řádek, pokud je z roku posledního sčítání if latest[country] == int(year): f.write(row) f.close()

Jestli se vám nechce rozbalovat soubor ručně, můžete ho číst rovnou jako zip (ale je to trocha práce navíc):

from zipfile import ZipFile from os import linesep z = ZipFile("school_attendance.csv.zip") f = z.infolist()[0] rows = f.read(fajl).decode("utf-8").split(linesep)

Grafika

Příklad. Vytvořte okno a vykreslete do něj Mandelbrotovu množinu.

Pro tenhle první grafický příklad budete potřebovat knihovnu Pillow. Její instalátor je ke stažení z neoficiálního repozitáře C. Gohlkeho, najděte verzi Pythonu, kterou máte na počítači instalovanou..

Mandelbrotova množina je jeden ze slavných fraktálů. Oproti jiným hezkým funkcím má velkou výhodu, že její hodnota v libovolném bodě se dá spočítat na pár řádcích kódu (níže ve funkci mandelbrot(x, y)). Podrobněji nemá smysl se jí teď věnovat. Kdybyste se na ni chtěli podívat pohodlněji, stáhněte si Xaos.

Ukázkový výsledek
Řešení. # -*- encoding: utf8 -*- import tkinter from PIL import Image, ImageTk def mandelbrot(x, y, limit=255): """Pro zadaný bod (x, y) v rovině navrací počet iterací 0 až 255 pro body mimo Mandelbrotovu množinu a 255 pro body uvnitř""" c = complex(x, y) z = c for n in range(limit): z = z**2 + c if abs(z) > 4: break return n # vyrobíme prázdný obrázek # "L" tady znamená Lightness, takže hodnota pixelu je jen číslo 0--255 # barevný by byl "RGB", potom musíte volat putpixel((x, y), (r, g, b)) width, height = 500, 500 img = Image.new("L", (width, height)) # v každém pixelu obrázku se podíváme na odpovídající bod v rovině a v něm vyhodnotíme funkci mandelbrot(x, y) for x in range(500): for y in range(500): image.putpixel((x, y), mandelbrot(2*x/width - 1.5, 2*y/height - 1)) # poprosíme o okno a nastavíme mu titulek tk = tkinter.Tk() tk.title("Mandelbrotova množina") # převedeme obrázek do jiného vnitřního formátu (jinak to nefunguje) pim = ImageTk.PhotoImage(img) # přidáme obrázek do okna tkinter.Label(tk, image=pim).pack() # dovolíme oknu, aby se staralo samo o sebe (funkce mainloop skončí teprve, když okno zavřeme) tk.mainloop()

Příklad. Vytvořte okno se skákajícím míčkem, který půjde ovládat.

Na tenhle příklad použijeme radši knihovnu Pygame. Z webu Pygame.org stáhněte pygame-1.9.2a0.win32-py3.2.msi (nebo jiný, jestli máte jiný operační systém).

Řešení doplním nejspíš během prázdnin, a na Pygame se podíváme ještě hodně dopodrobna.

Zpracování HTML a stahování z webu

Budete potřebovat knihovnu BeautifulSoup, kterou jsem pro vás stáhnul a poupravil.

Příklad. Stáhněte automaticky komiksy Hana a Hana. Buďto napište program, který podle zadání uživatele bude stahovat jen některé díly, nebo z výsledků vyrobte HTML stránku, kde budou přímo odkazy na příslušné obrázky.

Řešení. from urllib.request import urlopen from bs4 import BeautifulSoup def writeimage(src, filename): connection = urlopen(src) data = connection.read() connection.close() imgfile = open(filename, "wb+") imgfile.write(data) imgfile.close() def stahni(): obrazky = list() base_url = "http://kultura.idnes.cz/hanahana.asp" link = "" while not input("Zmacknete Enter pro stazeni dalsiho obrazku..."): connection = urlopen(base_url + link) doc = BeautifulSoup(connection) connection.close() obsah = doc.find(id="hanahana") a = obsah.find("a") link = a["href"] img = obsah.find("img") obrazky.append(img["src"]) return obrazky

Příklad. Stáhněte automaticky jízdní řád zadané zastávky pro všechny linky. Problém je s javascriptovou aplikací, která vládne na jizdnirady.idnes.cz   zatím mi ten kód nefunguje, je tady jen pro zvědavce.

Nefunkční kód. from urllib.request import urlopen from urllib.parse import urlencode from bs4 import BeautifulSoup url = "http://jizdnirady.idnes.cz/pid/zjr/" connection = urlopen(url) orig = BeautifulSoup(connection) connection.close() post = list() post.append(("Date", "18.12.2013 St")) post.append(("ctl00%24cDM%24cSC%24SelTTCity", "0")) post.append(("ctl00%24cDM%24cL%24t", "373")) post.append(("ctl00%24cDM%24cF%24t", "Sedlec")) post.append(("ctl00%24cDM%24cT%24t", "Kobylisy")) post.append(("dtcheckbox", "on")) post.append(("ctl00%24cDM%24cSB%24cmdSearch", "Hledat")) post.append(("__EVENTTARGET", "")) post.append(("__EVENTARGUMENT", "")) post.append(("__VIEWSTATEFIELDCOUNT", "2")) post.append(("__VIEWSTATE", orig.find(id="__VIEWSTATE")["value"])) post.append(("__VIEWSTATE1", orig.find(id="__VIEWSTATE1")["value"])) postdata = urlencode(post).encode("ascii") connection = urlopen(url, postdata) page = BeautifulSoup(connection) connection.close() out = open("jizdnirad.html", "w+") out.write(str(page)) out.close()

Doplňkové zápisky

Nic z následujícího jsem v hodině neprobral, ale může vám to prospět, chcete-li pochopit kód těch ukázek. Brzy po prázdninách se samozřejmě k těmhle tématům vrátíme a zápisky probereme.

Zápis funkcí

Když voláme nějakou funkci, můžeme jí parametry dávat buďto v patřičném pořadí, nebo je pojmenovat, pak na pořadí nezáleží. Pojmenované parametry se píšou jako název=hodnota. Je možné oba způsoby kombinovat, takže funkci voláme s prvními několika parametry nepojmenovanými a za nimi následují některé pojmenované.

print("Ahoj", "světe", end="..?", sep=" ")

Parametry, které funkci při volání nedáme, se nastaví na výchozí hodnotu. Výchozí hodnoty se píšou také zápisem název=výchozí_hodnota, ale ve funkci samotné.

def mocnina(x, y=2): return x**y

Tuple unpacking funguje i v parametrech funkce, ale moc se nepoužívá.

Když chceme s parametry dělat něco divočejšího, můžeme si je vyprosit všechny: nepojmenované jakožto seznam, pojmenované jakožto slovník. V následujícím zápise jsou důležité jen hvězdičky, názvy můžeme vybrat libovolně:

def secti(*args, **kwargs): for x in args: print(x) for i, x in kwargs.items(): print(i, ":", x)

Dělení a spojování řetězců

Funkce str.split(oddělovač) navrací seznam vzniklý rozdělením původního řetězce podle daných oddělovačů. Oddělovačem může být libovolný řetězec, například tečka: v takovém případě bude seznam obsahovat jednotlivé věty textu. V původním pořadí a už bez teček.

Pokud zavoláme str.split() bez parametru, chová se trochu zvláštně: rozdělí řetězec podle všech mezerám podobných řetězců. Může to být jedna nebo víc mezer, tabulátor, nový řádek a podobně, nebo jejich směs. Je to praktické, ale zásadně odlišné od volání split(" ")

Naopak, druhým parametrem můžeme nastavit maximální počet nalezených oddělovačů. Délka seznamu str.split(oddělovač, maxsplit) tedy bude maxsplit + 1.

Funkce str.join(sekvence) spojí zadané řetězce do jednoho. Mírně se liší zápisem od ostatních jazyků: řetězec před tečkou bude použitý oddělovač. Když chceme spojit seznam slov, zavoláme tedy " ".join(["nazdar", "světe"]). Když chceme spojit řetězce bez oddělovače, použijeme prázdný řetězec "".


Příklad. Napište funkci, která přičítá jedničku ke každému číslu v zadaném řetězci, čísla jsou oddělena čárkou. Funkce má navrátit opět řetězec čísel oddělených čárkou. Budete potřebovat použít cyklus, nejlépe s využitim enumerate, a převod řetězce na číslo a zpět int(řetězec), str(číslo).

>>> pricti("10,20,30") '11,21,31'

Práce se soubory

Textový soubor jde otevřít funkcí open(název, způsob). Funkce navrací otevřený soubor, se kterým můžeme dále pracovat. První parametr je obyčejně název souboru, ale pokud ho udáváme s celým umístěním na disku, kvůli kompatibilitě se používají i na Windows obyčejná lomítka / místo zpětných. Druhý parametr je řetězec udávající, co chceme se souborem dělat. Obvykle si vystačíme s "r" pro čtení a "w+" pro vytvoření nového souboru a zápis do něj. Pokud nezacházíme s textem, nýbrž s binárními daty, musíme do řetězce přidat znak "b".

Když se souborem přestaneme pracovat, musíme ho zavřít funkcí file.close(), jinak se data nezapíšou na disk. O stručnějším zápisu with open(...) as soubor: si povíme jindy.

Čtení souborů a zápis

Celý obsah souboru můžeme přečíst funkcí file.read(), bude to řetězec. Jako parametr můžeme funkci dát maximální počet znaků, které se mají přečíst.

Do souboru můžeme zapisovat řádek po řádku pomocí už známé funkce print(file=soubor, cokoliv) s pojmenovaným parametrem file. Zbytek volání se nemění, můžeme vypsat i víc hodnot za sebou. Když chceme zapsat libovolná data bez odřádkování, můžeme použít funkci file.write(řetězec).

Příklad. Vyrobte soubor plný teček a uložte ho do nějakého adresáře. Podrobněji, udělejte v souboru mřížku 80 řádků × 80 sloupců s mřížkami # na obou úhlopříčkách a tečkami všude jinde. Adresáře jdou v Pythonu samozřejmě vyrábět taky, ale pro tentokrát bude stačit, když ho vyrobíte ručně předem.

Importování jiných skriptů a knihoven

Importování obecně vzato slouží k načtení hotového kódu odjinud. Může načítat buďto ze systémových adresářů (tak jsme se s ním setkali dosud, například import math), anebo z adresáře, ve kterém Python právě běží – obyčejně to bude asi C: anebo adresář, ve kterém je dotyčný soubor .py.

Importovat jde buďto dynamickou knihovnu (.dll), nebo pythonský kód, anebo celý adresář plný kódu. To, co jde importovat, se za všech okolností nazývá modul. Ve všech zmíněných případech se na zápisu příkazu import nic nemění.

Příklad. Možných zápisů je ale několik. Vyzkoušejte si, co dělají následující příklady. Modul zůstane importovaný až do zavření příslušného okna Pythonu. Pro vyjasnění tedy možná budete potřebovat okno občas zavřít a spustit znovu.

from math import sin from math import sin as sinus import math import math as m from urllib.request import urlopen from math import *

Seznam některých významnějších modulů je na webu Py Package Index. Většinu z nich jde instalovat příkazem easy_install3 --user jméno_balíčku_který_chcete_instalovat z příkazové řádky operačního systému.