Python – Tipy & Triky

Python – Tipy & Triky

Dnes si ukážeme trošku Pythoní magie. Začneme s několika tipy ke vstupu/výstupu a výběru hodnot. Dále se zaměříme na řetězce, seznamy, n-ticemi a slovníky. Ukážeme si jak zapisovat slice konstrukce, generátory seznamů a další. Podíváme se i na lambda funkce, anonymní proměnné a nezapomeneme ani na třídní a statické metody. Na závěr si popíšeme pár užitečných vestavěných funkcí o kterých možná nemáte ani tušení.

1.0 VSTUP A VÝSTUP

1.1  Výstup na stderr

Občas se může hodit vypsat něco (třeba chybu ;) ) na standardní chybový výstup.

Příklad použití:

import sys
sys.stderr.write('Tento text je na stderr')

1.2  Čtení souvislého bloku textu ze stdin

Pokud potřebujete ze standardního vstupu číst víceřádkový vstup, můžete místo cyklu s voláním funkce raw_input() využít funkce read() na objekt stdin.

Příklad použití:

import sys
msg= sys.stdin.read()

Poznámka: Vstup musí být ukončen pomocí ^D (Ctrl+D) na samostatném řádku.

1.3  Souvislý blok textu v kódu

Pokud chcete mít ve zdrojovém kódu souvislý blok textu, stačí použít trojité uvozovky.

Příklad použití:

dlouhy_text = """
Nadpis
Dlouhatansky blok textu.
"""
print dlouhy_text

2.0 VÝBĚR HODNOT

2.1  Obdoba ternárního operátoru “vyraz ? hodnota1 : hodnota2”

Možná Vám, tak jako mně, občas v Pythonu chybí klasická Céčkovská konstrukce:

vysledek = výraz ? hodnota : hodnota;

Avšak v Pythonu si můžeme tuto konstrukci vytvořit také.
A to za pomocí logických operátorů “and” a “or”:

vysledek = výraz and hodnota or hodnota

POZOR! Pokud budete tuto konstrukci používat, je třeba aby “hodnota1” NIKDY nebyla (nemohla by být) interpretována jako False! V případě, že bude False, pak se stane první část výrazu, spojená pomocí and, nepravdivá a výsledkem bude automaticky hodnota2.

Příklad použití:

vysledek = slovnik.has_key('klic') and slovnik['klic'] or hodnota

Poznámka: Toto je jenom ilustrační příklad, samozřejmě v tomto konkrétním případě by bylo lepší použít metodu slovníku get() (viz dále).

2.2  Vhodnější možnost výběru hodnot

Kromě výše uvedeného způsobu jednořádkové volby hodnoty pomocí logických operátorů,
nabízí Python i konstrukci:

hodnota1 if vyraz else hodnota2"

Tato konstrukce je čistší způsob zápisu jednořádkového výběru hodnoty, ačkoli mně osobně se zdá méně přehledný.
Hlavní výhodou oproti výše uvedené konstrukci s and a or je, že odpadá problém špatného vyhodnocení, když je hodnota1 False.

Příklad použití:

cislo = 2
print "Cislo je vetsi nez 10" if cislo > 10 else "Cislo je mensi nez 10"

3.0 ŘETĚZCE/SEZNAMY/SLOVNÍKY/N-TICE

3.1  Iterace nad řetězcem/seznamem/n-ticí s “přidanou hodnotou”

Možná se Vám to už stalo, iterujete si přes nějaký objekt, provádíte operace s jednotlivými jeho prvky a najednou zjistíte, že by jste potřebovali znát index toho aktuálního.
S tímto Vám pomůže funkce enumerate(), která vrátí objekt, který během iterace vrací dvojici, ve které je první položka index a druhá požadovaný prvek.

Příklad použití:

retezec = "Slovo"
for index, znak in enumerate(retezec):
    print "Znak {0} je na indexu {1}".format(znak, index)

4.0 ŘETĚZCE

4.1  Test na přítomnost podřetězce v řetězci

Jak jednoduše otestovat, zdali řetězec obsahuje nějaký konkrétní podřetězec?
Odpovědí je šikovný operátor in.

Příklad použití:

retezec = "Ema ma maso."
if "Ema" in retezec:
    print "Retezec obsahuje zminku o Eve."

4.2  Test, zda je objekt řetězec

V Pythonu jsou dva objekty řetězců: str a unicode.
Pokud chcete testovat zda je objekt řetězec bez ohledu na to, jestli třídy str nebo unicode, testujte ho proti třídě basestring, která je nadtřídou těchto dvou tříd.

Příklad použití:

objekt = u"Unicode retezec"
if isinstance(objekt, basestring):
    print "Objekt je retezec!"

4.3  Test zda řetězec obsahuje pouze čísla

Příklad použití:

print "152".isdigit()

5.0 N-TICE

5.1  Zápis n-tice (tuple) s jedním prvkem

Možná jste si toho už všimli, ale zápis (6) Vám n-tici nevytvoří;)
Výsledkem tohoto konkrétního zápisu je celé číslo s hodnotou 6.
Pokud chcete zapsat n-tici, která obsahuje jenom jeden prvek, musíte ji zapsat takhle: (prvek, ).

Příklad použití:

ntice = (6,)

6.0 SLOVNÍKY

6.1  Bezpečný přístup do slovníku

Pokud budeme přistupovat do slovníku na klíč, který v něm neexistuje, nebude se to Pythonu líbit a vrátí nám výjimku KeyError.

Řešit se to dá různě:
1) Použít try/except a výjimku odchytit.
2) Otestovat, zdali klíč ve slovníku opravdu existuje pomocí operátoru in.
3) Použít metodu slovníku get().

Použití metody get s sebou nese výhodu, kterou je možnost nastavit defaultní hodnotu, která se má vrátit při neexistenci daného klíče.

Příklad použití:

vysledek = slovnik.get('klic', defaultni_hodnota)

Poznámka: V případě, že vynecháte druhý parametr a klíč se ve slovníku nenachází, bude vráceno None.

6.2  Iterace nad slovníkem

Nad slovníkem můžete iterovat několika způsoby:
Nad klíčí pomocí metody:

iterkeys() (případně iter(slovnik))

Nad hodnotami pomocí metody:

itervalues()

Nad dvojicí (klíč, hodnota) pomocí metody:

iteritems()

7.0 SEZNAMY

7.1  Slicing seznamu

Slicing je v Pythonu široce používaná konstrukce pro získávání dat z iterativních datových typů jako jsou seznamy (list), n-tice (tuple) a řetězce (string).

Příklad použití:

>>> # Pro další příklady budeme předpokládat seznam:
>>> a = [1, 2, 3 , 4]
>>> # První prvek seznamu:
>>> a[0]
1
>>> # Poslední prvek seznamu:
>>> a[-1]
4
>>> # Celý seznam:
>>> a[:]
[1, 2, 3, 4]
>>> # Obrácení (reverse) seznamu:
>>> a[::-1]
[4, 3, 2, 1]
>>> # Seznam s krokem 2:
>>> a[::2]
[1, 3]
>>> # Poslední 2 prvky seznamu:
>>> a[-2:]
[3, 4]
>>> # První 3 prvky seznamu:
>>> a[:3]
[1, 2, 3]
>>> # Vše kromě prvních 2 prvků:
>>> a[2:]
[3, 4]
>>> # Určitý rozsah seznamu:
>>> a[1:3]
[2, 3]

7.2  Pěkná textová reprezentace seznamu

Jak jednořádkovým zápisem vytisknout seznam s pěkným formátováním?
Odpověď nám dá funkce join().

Příklad použití:

zelenina = ['Rajce', 'Mrkev', 'Okurka', 'Paprika']
print "n".join(zelenina)

Poznámka: Nový řádek ‘n’ samozřejmě můžete nahradit libovolným textem, který chcete použít jako oddělovač jednotlivých položek seznamu.

7.3  Generátor seznamu (List comprehension)

Python nám umožňuje velice efektivně zapsat operace vytvářející nové seznamy.

Pojďme si ukázat pár příkladů:

[x*2 for x in a]

Vytvoří seznam obsahující dvojnásobné hodnoty než seznam a.

[x for x in a if x > 3]

Vytvoří seznam obsahující hodnoty ze seznamu a, které jsou větší než 3.

[x*2 for x in xrange(10) if x**2 > 3]

Z rozsahu čísel 0 až 9, jejichž druhá mocnina je větší než 3, vytvoří seznam jejich dvojnásobků.

7.4  Vnořené cykly v generátoru seznamu

Co když ale potřebujete vygenerovat složitější seznam?
Třeba takový, co by se generoval několika cykly?
Žádný problém.

Příklad generování seznamu zapsaný klasicky:

vysledek = []
for x in xrange(5):
    for y in xrange(5):
        if (x - y) > 0:
            vysledek.append((x, y))

A teď významově stejný zápis pomocí generátoru seznamu:

vysledek = [(x, y) for x in xrange(5) for y in xrange(5) if (x - y) > 0]

7.5  Generátorový výraz (Generator expression)

(Generátorové výrazy sice pod seznamy nepatří, ale mají k seznamům syntakticky blízko a protože se generátory používají pro nahrazení seznamů, rozhodl jsem se je zařadit na toto místo.)

Generátorový výraz nám umožní zapsat generátor jednořádkově, téměř stejně jako výše uvedené generátory seznamu. Jediný rozdíl jsou závorky. Generátorové výrazy používají kulaté “()” místo hranatých “[ ]”, které používají generátory seznamů.

Poznámka pro ty co neví nic o generátorech:
Generátory jsou vhodné na iterace, při kterých nám stačí pracovat vždy jen s aktuálním prvkem posloupnosti a není třeba přistupovat k ostatním. Jednotlivé prvky jsou generovány až během iterace ve chvíli, když jsou potřeba. Výhodou generátorů je uspoření paměti.

Příklad použití:

generator = (x for x in xrange(5) if x % 2 == 0)

7.6  Podmínky nad seznamy – existuje prvek který splňuje?

Jsme v situaci, kdy potřebujeme zjistit zdali alespoň jeden prvek v seznamu splňuje určitou podmínku.
Jak efektivně na to?
Použijeme funkci any().

Příklad použití:

vysledky = [101, 99, 105, 106, 105]
if any(vysledek < 100 for vysledek in vysledky):
    print "Exituje nekdo dosahl skore mensiho nez 100!"

Poznámka: Výhodou funkce any() je, že hledá pouze tak dlouho, dokud nenarazí na první prvek splňující podmínku a pak okamžitě hledání ukončí. Další hledání by už nemělo smysl, protože výsledek by stejně zůstal True (pravda).

7.7  Podmínky nad seznamy – platí, že všechny prvky splňují?

Jsme v situaci, kdy potřebujeme zjistit zdali všechny prvky v seznamu splňují určitou podmínku.
Jak efektivně na to?

Použijeme funkci all().

Příklad použití:

vysledky = [101, 99, 105, 106, 105]
if all(vysledek > 100 for vysledek in vysledky):
    print "Vsichni dosahli vysledku lepsiho nez 100 bodu!"

Poznámka: Výhodou funkce all() je, že pokud nalezne prvek nesplňující podmínku, ukončí další hledaní a vrátí False. Další hledání by už totiž nemělo smysl, protože výsledek by stejně zůstal False (nepravda).

7.8  Otestování, zda je seznam prvků unikátní

Unikátní seznam je takový, který neobsahuje duplicitní záznamy. Prostě jde o seznam, ve kterém nenajdete dva a více stejných prvků.
Při testu na unikátnost seznamu v Pythonu využijeme datového typu množina (set), na který seznam převedeme. Množina se vyznačuje tím, že je vždycky unikátní. Pokud tedy měl původní seznam duplicitní prvky, tak při převodu na množinu budou duplicity odstraněny.

Příklad použití:

pismena = ['a', 'b', 'c', 'd', 'a']
if len(pismena) == len(set(pismena)):
    print "Seznam obsahuje pouze unikatni prvky!"

7.9  Součet všech prvků seznamu

Součet všech prvků seznamu provedeme pomocí vestavěné funkce sum().

Příklad použití:

seznam = [1, 2, 3, 4]
print sum(seznam)

8.0 OSTATNÍ

8.1  Zřetězení operátorů porovnání

Pokud potřebujete porovnat vzájemně několik hodnot, můžete za sebe operátory řetězit přímo, bez použití logické spojky and.

Příklad použití:

if a < 5 < b:
    print 'Tento zapis je ekvivalentni zapisu: if a < 5 and 5 < b:'

8.2  Výměna hodnot

Prohození hodnot dvou proměnných v Pythonu:

a,b = b,a

8.3  Argumenty příkazové řádky

Jednou z důležitých znalostí je umět přistupovat k argumentům příkazové řádky.
V Pythonu se k nim dostanete pomocí modulu sys a jeho atributu argv.

Příklad použití:

import sys
print sys.argv

8.4  Anonymní proměnné

Anonymní proměnná se značí podtržítkem _ a používá se na místech, kde je nějáká proměnná vyžadována, ale její hodnota může být ignorována.

Příklad použití:

def funkce()
    return ('Ahoj', 4)
slovo, _ = funkce()

8.5  Else bloky u cyklů

U cyklu for a while můžete použít nepovinný blok else.
Tento blok se provede při ukončení cyklu.
Jeho výhodou je, že v případě, že cyklus předčasně ukončíte pomocí příkazu break, nebude else větev provedena.

Příklad použití:

for i in xrange(5):
    pass
else:
   print 'Cyklus se provedl.'

8.6  Přirozenější počítání

Počítače nejsou přesné, to se učí (nebo by mělo) v každém  kurzu programování.
Jak známo, většina počítačů pracuje ve dvojkové soustavě. Stejně jako v kterékoli jiné soustavě i v té dvojkové existují hodnoty, které v konečném prostoru přesně uchovat nepůjdou.

Je to stejné jako když se budete snažit v desítkové soustavě zobrazit výsledek odmocniny ze dvou. To prostě nepůjde, na jeho zobrazení by jste potřebovali rozvoj na nekonečně mnoho desetinných míst.
Díky této vlastnosti Vám například Python na příkaz 0.1 + 0.1 + 0.1 – 0.3 dá výsledek: 5.5511151231257827e-17.

No jo, ale co když třeba zrovna programujete účetní program? Tam by jste raději preferovali výsledek 0…

Jednou z možností je výsledky zaokrouhlovat pomocí round() na zvolený počet desetinných míst.
Druhou možností je použít modul decimal, který se při počítaní přece jen chová přirozeněji a vrátí výsledky, které by jste očekávali.

Příklad použití:

from decimal import *
print Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')

8.7  Spuštění příkazu v shellu

Chtěli by jste v určitém místě programu například vyčistit terminálové okno?
Pomůže nám modul subprocess.

Příklad použití:

import subprocess
subprocess.call('clear')

8.8 Spuštění příkazu/programu a přečtení jeho výstupu na stdout

Jak v pythonu spustit program a přečíst co nám vypsal na stdout? Jednoduše pomocí modulu subprocess.

Příklad použití:

import subprocess
ret = subprocess.Popen(['echo', '"Test"'], stdout=subprocess.PIPE)
vystup = ret.stdout.read()
print vystup

9.0 FUNKCE

9.1  Lambda funkce

Lambda funkce je takzvaná anonymní funkce. Tím, že je anonymní se myslí to, že nemá jméno a nemůžete ji pomocí jména volat.
Hlavní využití má lambda funkce jako argument při předávání parametrů. Pokud funkce jako argument přijímá jinou funkci jako třeba: map(), reduce() apply(), filter() a další. Požití lambda funkce Vám může ušetřit dva řádky kódu na kterých by jste jinak museli definovat pojmenovanou funkci.

Příklad použití:

print reduce(lambda x, y: x+y, [1, 2, 3, 4])

9.2  “Zrada” u defaultních argumentů funkce

Python má, co se týče defaultních argumentů, jednu zvláštnost. Defaultní hodnota se pro mutable objekty (seznam, slovník atd.) vyhodnotí jenom jednou! Při dalším zvolání té samé funkce, jí bude přiřazen ten stejný seznam jako v předchozím volání. Takže pokud tento seznam modifikujete, tak během příštího zavolání bude funkce pracovat s tímto změněným seznamem.

Lépe to snad bude jasné z příkladu:

def funkce (prvek, seznam = []):
    seznam.append(prvek)
    print seznam

funkce('a')
funkce('b')

Takže pozor na to!

9.3  Předání parametrů v seznamu funci

Máme situaci, kdy potřebujeme volat funkci, ale její parametry máme v seznamu.
Aby jsme se vyhnuli zápisu:

funkce(seznam[0], seznam[1])

Můžeme použít zápis:

funkce(*seznam)

Příklad použití:

seznam=['Windows', 'Linux']
"Pouzivam Windows".replace(*seznam)

9.4  Předání parametrů ve slovníku funkci

U slovníku je syntaxe podobná jako u seznamu, akorát místo jedné hvězdičky použijete dvě.
Je ale potřeba mít na paměti, že v případě slovníku není zaručeno pořadí prvků, takže prvky se nepřiřazují na základě pořadí jako u seznamu, ale na základě klíčů. Klíče tedy musí odpovídat proměnným.

Příklad použití:

def funkce(a, b, c):
    print a, b, c

slovnik=dict(c=6, a=5, b="Ahoj")
funkce(**slovnik)

10.0 TŘÍDY

10.1  Statické metody

Statická metoda je metoda, kterou je možno volat přímo, bez instance konkrétní třídy, které náleží. V podstatě se na ni můžeme dívat jako na obyčejnou funkci, jejíž jedinou zvláštností je, že je dostupná z prostoru jmen konkrétní třídy.
Statickou metodu vytvoříte pomocí dekorátoru @staticmethod.

Příklad použití:

class Trida(object):
    @staticmethod
    def staticka_metoda():
        print "Volana staticka metoda."

Trida.staticka_metoda()

10.2  Třídní metody

Třídní metoda je metoda, kterou je možno volat přímo, bez instance konkrétní třídy, které náleží. Na rozdíl od statické metody, má třídní metoda informaci, pomocí které třídy byla volána. Díky tomu je schopná identifikovat, jestli je volána ze své vlastní třídy, nebo z podtřídy.
Třídní metodu vytvoříte pomocí dekorátoru @classmethod.

Příklad použití:

class Trida(object):
    @classmethod
    def tridni_metoda(cls):
        print "Volana tridni metoda za pomoci tridy: {0}.".format(cls)

Trida.tridni_metoda()

11.0 ZAJÍMAVÉ VESTAVĚNÉ FUNKCE

Seznam vestavěných funkcí naleznete v dokumentaci.

11.1  bin(x)

Vrátí textový řetězec reprezentující binární podobu předaného celého čísla.

Příklad použití:

print bin(15)

11.2  hex(x)

Vrátí textový řetězec reprezentující hexadecimální podobu předaného celého čísla.

Příklad použití:

print hex(15)

11.3  oct(x)

Vrátí textový řetězec reprezentující podobu předaného celého čísla v osmičkové soustavě.

Příklad použití:

print oct(15)

11.4  ord(c)

Vrátí celé číslo odpovídající ASCII/Unicode hodnotě zadaného znaku.

Příklad použití:

print ord('a')
print ord(u'ř')

11.5  chr(i)

Vrátí řetězec dlouhý jeden znak, kterému odpovídá předaná celočíselná hodnota v ASCII.

Příklad použití:

print chr(82)

11.6  unichr(i)

Vrátí Unicode řetězec dlouhý jeden znak, kterému odpovídá předaná celočíselná hodnota v Unicode.

Příklad použití:

print unichr(223)

11.7  divmod(a, b)

Díky této funkci provedete současně dvě operace: celočíselné dělení a modulo.
Výsledkem je dvojice jejíž první prvek je výsledek celočíselného dělení a druhým je modulo (zbytek po celočíselném dělení).

Příklad použití:

print divmod(5, 2)

11.8  reversed(sekvence)

Vrátí iterátor pro iteraci v obráceném pořadí.

Příklad použití:

seznam = [1, 2, 3, 4]
for cislo in reversed(seznam):
    print cislo,

11.9  round(x[, n])

Zaokrouhlí float na n desetinných míst.
n je nepovinný argument, v případě vynechání, je defaultně provedeno zaokrouhlení na 0 desetinných míst.

Příklad použití:

print round(15.486, 2)
Comments are closed.