Objekty

Jeden z možných náhledů na objekt je, že se jedná o obal na proměnné. Místo toho, abychom proměnnou použili přímo, píšeme potom objekt.proměnná – s tímto zápisem jsme se mnohokrát setkali už i v Javascriptu. Podobným způsobem může objekt obsahovat funkci, v takovém případě místo slova funkce většinou použijeme slovo metoda. Metody můžou svůj objekt upravovat, takže jsou to vlastně nástroje, které můžeme na objekt nějakým způsobem použít.

Názvy, které za tečku píšeme, ale nemusí být všechno, co v objektu je, a naopak vůbec nemusí být nikde v paměti uložené (nemusí to být opravdové proměnné). O tom, jak objekt v počítači opravdu je vyjádřený, nemáme ponětí.

Každý objekt má určitý typ, což můžeme zjistit tím, že na něj zavoláme funkci type(něco). Python nám nedává záruku, že se objekty stejného typu budou chovat stejně, ale většinou to tak bývá (například: čísla jde sčítat, ze seznamů jde vybírat indexováním a podobně). K tématu typů se vrátíme příští týden.

>>> type("řetězec") <class 'str'> >>> type(1.7) <class 'float'> >>> type([]) <class 'list'>

V Pythonu je objektem vlastně všechno. Cokoliv, co jsme zatím dávali do proměnných, tedy čísla, booleovské hodnoty, řetězce, seznamy, n-tice a slovníky, byly objekty. Typ objektu je objekt. Funkce jsou objekty. Za určitých okolností i kód programu a jeho komentáře můžou být objekty.

Objekty v Pythonu můžou být uložené všelijak, ale jakousi základní hlavičku mají v paměti zapsanou vždy stejným způsobem. To umožňuje porovnávat, jestli je ve dvou proměnných tentýž objekt (obě proměnné vedou na stejnou hlavičku), nebo jsou dva různé objekty, byť třeba velmi podobné. Takové porovnání se provádí podmínkou is, například True is True. Když nastavíme jednu proměnnou do druhé (například x = y, za předpokladu že v proměnné y už předem něco bylo), budou určitě tentýž objekt, takže bude platit x is y.

I když se dva objekty rovnají, nemusí být tentýž. Hezky se to předvede se seznamy. V následující ukázce si všimněte také toho, že když seznam změníme v jedné části programu, změní se všude.

>>> s = [1,2,3] >>> t = [1,2,3] >>> s == t True >>> s is t False >>> u = s >>> u.append(4) >>> s [1, 2, 3, 4] >>> t [1, 2, 3]

Všechny hodnoty obsažené v objektu – jeho atributy – jde získat voláním funkce dir(). Některé z nich jsou obalené dvojitými podtržítky, což znamená, že bychom si s nimi zatím neměli plést hlavu.

>>> dir("řetězec") ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] >>> "řetězec".upper() 'ŘETĚZEC'

Příkaz import

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 skript .py, který jsme spustili.

Importovat jde buďto dynamickou knihovnu (obvykle .dll nebo .pyd), 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říkazy. 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 *

Většina knihoven nabízí pro pohodlí úhledné instalátory, které fungují náramně, ale bohužel vyžadují administrátorská práva. Proto si na školních počítačích budeme muset vypomáhat různými obezličkami. Na vlastních počítačích samozřejmě můžete instalátor použít, vyhnete se tak spoustě komplikací. Samotný kód vašich programů bude stejný, ať knihovnu dostanete do počítače jakkoliv.

Odbočka: jak importovat odjinud

Když chceme importovat knihovnu, která není instalovaná přímo do systému, musíme Pythonu poradit, kde ji má hledat.

Možnost 1: (upřednostňovaná) spustit python jinde. Když napíšete skript, tj. soubor s koncovkou .py, a poklikáte na něj, spustí se Python v příslušné složce. Bez potíží tedy můžete importovat knihovny, které jsou ve stejné složce jako váš skript.

Možnost 2: spustit python a přejít jinam. Python (jako každý jiný program) může operační systém poprosit a přejít do jiné složky na disku. Také to budeme potřebovat někdy pro psaní do souborů. Všechny potřebné funkce jsou v modulu os: změnit adresář můžete funkcí chdir (change directory), zjistit ten současný pomocí getcwd (get current working directory). Nadřazená složka se vždy jmenuje "..". Následující ukázka používá unixový systém souborů, proto na začátku není žádné C:.

from os import chdir, getcwd >>> getcwd() '/home/addam' >>> chdir("..") >>> getcwd() '/home' >>> chdir("addam") >>> getcwd() '/home/addam'

Možnost 3: vysvětlit importu, že má číst odjinud. Složky, do kterých se Python během importování zkusí podívat jsou (v daném pořadí) uložené jako proměnné path v modulu sys. Můžete s nimi dělat, co chcete, například něco přidat na konec:

import sys sys.path.append("C:/Documents and Settings/Karel/Škola")

Jsou ještě další možnosti, ale ty jsou ještě ošklivější. A v případě možností zde označených jako 2 a 3 ani neplatí, co jsem sliboval na konci předchozího oddílu: kód programu musíte měnit. A jsou s nimi problémy.

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

V hodině jsme příklad neprobrali, vrátíme se k němu 14. ledna.

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 nebo jinou verzi Pythonu než 3.2) a nainstalujte ho. Pokud pracujete na školních počítačích, stáhněte místo toho vhodný soubor z webu C. Gohlkeho, přejmenujte instalátor na koncovku .zip, otevřete ho vhodným správcem archivů (například 7Zip) a rozbalte složku pygame vcelku do složky, kde píšete svůj skript.

Následující ukázka využívá soubor ball.png, ten musí být uložený ve stejné složce jako váš skript. Můžete použít následující obrázek míče, který jsem stáhnul z Wikipedie:


Kód k dokončení. import pygame import pygame.locals as pl pygame.init() clock = pygame.time.Clock() screenrect = pl.Rect(0, 0, 640, 480) screen = pygame.display.set_mode(screenrect.size) pygame.display.set_caption('Kravinky v Pygame') black = pygame.Color(0, 0, 0) white = pygame.Color(255, 255, 255) ball = pygame.image.load('ball.png') position = ball.get_rect() background = pygame.Surface(screenrect.size) background.fill(white) screen.blit(background, (0,0)) alive = True while alive: for event in pygame.event.get(): if event.type == pl.QUIT or (event.type == pl.KEYDOWN and event.key == pl.K_ESCAPE): alive = False elif event.type == pl.MOUSEBUTTONDOWN: # kresleni na obrazovku pygame.draw.circle(background, black, event.pos, 5, 0) pygame.draw.circle(screen, black, event.pos, 5, 0) keystate = pygame.key.get_pressed() horz = keystate[pl.K_RIGHT] - keystate[pl.K_LEFT] vert = keystate[pl.K_DOWN] - keystate[pl.K_UP] # vymazeme plochu, kde byl mic posledne screen.blit(background, position, position) # posuneme mic position = position.move(horz, vert) # vykreslime mic na nove pozici screen.blit(ball, position) pygame.display.update() clock.tick(30) # 30 FPS pygame.quit()

Vlastní třídy

Pojem třída znamená víceméně totéž co "typ objektu". V tomhle nadpise jsem mu dal přednost, poněvadž se budeme zaobírat klíčovým slovem class.

Než se podrobněji pustíme do syntaxe, je potřeba si ujasnit trochu obecných znalostí. Objekty, přesněji jejich instance, jsou nějakým způsobem uložené v paměti. Když máme jednu instanci ve dvou různých proměnných, můžeme si to ověřit porovnáním x is y. Každý objekt je nějakého typu, a ten jde zjistit voláním funkce type. Nové instance nějakého typu vyrobíme obvykle tak, že typ zavoláme – například list() vyrobí nový objekt typu list. Objekty typů jako jsou čísla, řetězce a podobně jdou samozřejmě vyrábět prostě tak, že potřebné číslo (apod.) napíšeme, ale to se dá chápat spíš jako výjimka.

Tohle volání může být matoucí, protože typ objektu zjevně není funkce. Snad není třeba zabíhat do podrobností, Python je prostě stavěný tak, aby to pochopil správně. K volání nějaké funkce ve skutečnosti dojde, a bude to metoda __init__ nově vytvořeného objektu. Všimněte si, že její název začíná i končí dvěma podtržítky, což naznačuje, že má nějaký speciální význam. Říká se jí konstruktor.

Je čas na ukázkový kód.

class Ball: def __init__(self, filename): self.image = pygame.image.load(filename)

Pozoruhodnosti v kódu:

Zápisky nejsou hotové, včas je dokončím.