Přejít k navigační liště

Zdroják » Různé » Python profesionálně: úvod

Python profesionálně: úvod

Články Různé

Programovací jazyk Python přispívá k rychlému vývoji. Dovolí nám nesoustředit se na technické detaily a nechává nám více prostoru na skutečné řešení problému. Python se sice snaží být intuitivní, ale obsahuje věci, které nejsou všední, a příliš se o nich neví. Tímto dnes začínajícím seriálem vám chci Python více přiblížit a odkrýt vám jeho krásu.

Úvod k seriálu

Python je velmi zajímavý jazyk. Opravdu je. Na první pohled může vypadat obyčejně, jen s trochu dobrými vychytávkami, avšak po detailnějším zkoumání je tomu jinak. S Pythonem jde vývoj rychle. Nemusíte stále dokola řešit stejné věci. Python pomáhá nové vlastnosti naprogramovat znovupoužitelně.

Co z Pythonu vám chci ukázat? Něco se hodí do příručky pro zelenáče, něco vyžaduje mít jisté znalosti. Zahrnul jsem vše, co mi přišlo zajímavé, a o čem se málo ví. Vznikl tak seriál, kde si snad každý najde to svoje. Dnes začneme ukázkou syntaktických záležitostí a postupně se můžete těšit na různé užitečné tipy, návrhové vzory po pythonovsku a nakonec se těšte na povídání o metatřídách.

Všechny ukázky plně fungují v Pythonu 2.x. Úpravy pro Python 3 jsou minimální, takže se o nich ani nezmiňuji. Pokud však existuje v Pythonu 3 něco navíc nebo se tam vyskytuje nějaká zásadní změna, tak se o tom zmíním.

Začínáme

Pořadí bude, jak už jsem zmínil, od toho nejlehčího, tak schválně, kde odpadnete. :-) Pojďme nyní na první ukázku!

(lambda row: ' '.join(str(cell) if isinstance(cell, (int, long)) else ' ' if cell is None else (cell[::-1].capitalize() if not idx else cell) for idx, cell in enumerate(row) if cell))([6*7, 'is', None, 'rewsna'][::-1])

Uff, z ukázky jsou vidět dvě věci, možná tři: Za prvé, je to nečitelné. Takovým konstrukcím se určitě vyhýbat! Za druhé – v Pythonu je možné prasit, i když nabádá ke štábní kultuře. Proto programujte s otevřenýma očima. A za třetí, jen jsem vás chtěl trochu vylekat. Klid. A teď už se do toho opravdu pusťme.

Ternární operátor

Začneme ternárním operátorem. Já jsem ho dlouho neznal a vadilo mi, že v Pythonu není (ach, jak pošetilé je důvěřovat knížkám). Nejprve jsem to tedy dělal klasicky přes podmínku.

if y:
    x = 'some string'
else:
    x = 'other string'

Zdlouhavé. Když už nic lepšího, alespoň jsem si to zjednodušoval (což lze ve všech jazycích), ač trochu neefektivně. V dnešní době však není podstatné mít efektivitu neustále na paměti.

x = 'other string'
if y:
    x = 'some string'

Když tu jsem jednoho dne prozřel – našel jsem náhražku za ternární operátor!

x = y and 'some string' or 'other string'

Bohužel netrvalo moc dlouho a narazil jsem na problém, kde to nevyhovuje. To když přiřazovaná hodnota při kladném vyhodnocení podmínky je v booleanském smyslu falešná. Ukázka objasní:

x = False and 'a' or 'b' # 'b'
x = True and 'a' or 'b' # 'a'
x = False and '' or 'b' # 'b'
x = True and '' or 'b' # 'b' - ajajaj

Pokud jste tedy nuceni používat Python starší než 2.5 a chcete využívat této konstrukce, dejte si pozor! Případně použijte menší trik (bohužel už to je nepřehledné a raději bych se tomu vyhnul):

x = (True and [''] or ['b'])[0]

Nebudu už ale napínat – jakže vypadá (bezchybný) ternární operátor v Pythonu dostupný od Pythonu 2.5? Takhle:

x = 'some string' if y else 'other string'

Na první pohled se to může zdát trochu nelogické, ale jde jen o zvyk. Zkuste si říct v hlavě klasický ternární operátor ?:. Budete říkat něco jako „když je tohle takhle, tak tamto, jinak tamhleto.“ Zatímco tento lze hezky česky přečíst jako „tamto když je tohle takhle, jinak tamhleto.“ Což mně osobně přijde lepší.

A lze samozřejmě také hezky řetězit…

x = 'variable is %s' % 'one' if y == 1 else 'two' if y == 2 else 'three'

Místo řetězení je ale už lepší použít klasické podmínky. Nebo alespoň přidat závorky, protože to u složitějších konstrukcí může oklamat i takového Tuvoka!

I cyklus má svůj blok else

Řekl bych, že o tom ví velmi málo lidí. A opravdu for cyklus může mít blok else (pravděpodobně záviděl podmínce, holomek). Mockrát se to nepoužije, to je pravda, ale ani tak kvůli nevhodnosti, jako kvůli nezažití. Už jsem si na něj párkrát vzpomněl a byl mi užitečný. Proto se o něm zmiňuji.

Vezměme si příklad: máme seznam automobilů a u jednoho (nebo i u více) potřebujeme odemknout kufr. Pokud ale nenajdeme automobil, u kterého ten kufr potřebujeme odemknout, musíme zavolat nějakou rutinu, třeba informovat uživatele, že pravděpodobně někdo automobil odcizil. Normálně by se napsalo něco jako:

obj = None
for item in listOfCars:
    if item.isCarWhichILookingFor():
        obj = item
        obj.unlockTrunk()
        break

if obj is None:
    print 'Somebody stole car!'

Je to poměrně upovídané řešení. A co je upovídané, u toho je větší šance vzniku chyb. Proto si teď ukážeme, jak funguje blok else u cyklu. Slovy: jestliže cyklus doběhne bez přerušení až nakonec, provede se i blok else, jinak nikoliv. Ukázka:

for x in range(5):
    if x == 1:
        break
else:
    print "else" # Zde se else nevypise.

for x in range(5):
    pass
else:
    print "else" # Zde se else vypise.

S novými vědomostmi zkusíme původní ukázku upravit. Zřejmě už tušíte jak.

for item in listOfCars:
    if item.isCarWhichILookingFor():
        obj.unlockTrunk()
        break
else:
    print 'Somebody stole car!'

Blok else nezáviděl pouze cyklus for, ale také while. Funguje to pochopitelně úplně stejně.

x = 1
while x <= 5:
    try:
        print '%d. attempt to connect to the database.' % x
        connectToDatabase()
    except ConnectTimeoutException:
        x += 1
    else:
        break
else:
    print 'Connection Error!'

Iterace v opačném pořadí

Z předešlého příkladu máme seznam automobilů. S tímto seznamem chceme něco udělat (třeba vypsat do souboru a odeslat kamarádovi), ale v opačném pořadí. Céčkař by pravděpodobně psal šílená céčkovská céčka (nic proti :-).

for i in range(len(listOfCars)-1, -1, -1):
    obj = listOfCars[i]
    # Do something...

Ale my jsme přeci pythonisti! Takže zkusme ukázku upravit:

listOfCars .reverse()
for item in listOfCars:
    # Do something... 

Bohužel to ale zmodifikuje celý seznam. Mohu být zrovna uvnitř nějaké metody, která tento seznam dostala parametrem, a přeci nebudu někomu měnit objekty pod rukama. Pravděpodobně by programátor volající naši metodu nebyl zrovna nadšen. Proto sáhneme po built-in funkci, která iteruje nad seznamem (nebo jakékoliv jiné seznamové instanci) v opačném pořadí.

for item in reversed(listOfCars):
    # Do something...

Teď už to je dobré. Samotný list neměním a nemusím se moc upisovat. Ale stále to lze zkrátit. Pomůžu si takzvanou slice notation ( listOfCars[…]). A že to nejde? Že lze pouze ze seznamu určovat „výřezy“? Kdepak…

for item in listOfCars[::-1]:
    # Do something...

Ona slice notace má totiž ještě třetí parametr, o kterém moc lidí neví, a ten určuje, o kolik se má iterace posouvat na další položku; defaultně o jednu. Tedy [2:3] je to samé, jako [2:3:1], tedy vezme to třetí položku (jedná se o interval zprava otevřený). Pokud napíšu [0:6:2], tak to vycucne první, třetí (skok o dva) a pátou (zase skok o dva) položku; dál už to nepůjde, protože je to omezené zprava.

Slice notace lze dokonce zapsat i built-in metodou slice a tuto instanci (kterou ta metoda vrátí) použít jako klasickou slice notaci.

sl = slice(None, None, -1) if reversedOrder else slice(None)
for item in listOfCars[sl]:
    # Do something...

Tím si můžeme připravit scénář průchodu seznamem v jedné funkci a vykonat iteraci v druhé. Podle mého názoru slice notace už nemůže být lepší!

Hrátky s proměnnými

Čas od času je potřeba vrátit z funkce více hodnot. Řešit tuto potřebu lze různě, od vracení seznamu čí slovníku přes vracení nějaké jiné speciální instance až po rozdělení na více funkcí. Záleží na okolnostech, co je zrovna vhodnější. Například můžeme chtít mít funkci, která z nějakého vstupu rozparsuje klíč a hodnotu:

def parseSameInput(input):
    # Hloupy Honza pro prezentacni ucely.
    return input.split('=')

output = parseSomeInput('key=value')
k = output[0]
v = output[1]

Řešení to je jednoduché, ale stále to není po pythonsku. Kdo by se chtěl takhle upisovat? Existuje snadnější způsob a řekl bych, že už jej znáte, jen si neuvědomujete možnost ho použít kdekoliv.

output = parseSomeInput('hello=world')
k, v = output

Tento způsob se vlastně používá hojně při iteraci slovníku, to staré známé for k, v in d.iteritems(). Ukázka lze však ještě více zjednodušit (všimněte si, že funkci není třeba nijak upravovat).

k, v = parseSomeInput('foo=bar')

A jak to funguje? Nijak zázračně, stačí si uvědomit, že jakmile uděláme čárku, je z toho tuple. A tuple lze rozložit do více proměnných.

a = 3, 5
b = (3, 5)
if a == b:
    print "Promenne jsou stejne!"

Tím lze i snadno prohodit proměnné – pamatujete si na váš první řadící algoritmus bubble sort, kde jste prohazovali proměnné, a museli si nadefinovat pomocnou proměnnou? Zkusme to nyní znovu v Pythonu.

tmp = a
a = b
b = tmp

# vs.

a, b = b, a

Tím ale naše možnosti nekončí, nový Python 3 zvládne ještě jednu specialitu. Ono je to ve skutečnosti logická věc, ale ne každému to může dojít (a vývojářům při vývoji Pythonu 2 ani nedošlo) – tuple (nebo seznam) smí obsahovat více prvků, než do kolika proměnných má být rozložen.

one, two, three, *fourfivesix = range(1, 7)

Jen je potřeba nezapomenout na hvězdičku u poslední proměnné, která má pojmout zbytek.

A když už jsem u toho definování proměnných, tak ještě přidám zmínku na built-in funkce locals a globals. První zmíněná vrací referenci na slovník s lokálními proměnnými a druhá s globálními proměnnými. Když se nad tím člověk zamyslí, tak lze klidně vytvořit následující absurdum.

locals().update(dict((chr(k), v) for k, v in zip(range(97,102), range(1,6))))

Předchozí ukázka v lokálním kontextu vytvoří pět proměnných ae s postupnými hodnotami 1 až 5. Zkuste si to rozluštit sami.

Závěr

Jak je vidět, Python hodně přispívá k rychlému vývoji. Byla by velká škoda ho minimálně nezkusit, protože dnešními tipy to nekončí, dnes to byly spíš jen takové srandičky. Příště budeme pokračovat a konkrétně se podíváme na některé pokročilejší techniky jako generátory, lambda funkce či with konstrukce. Dnes už jen přidám pár odkazů pro další studium:

Komentáře

Subscribe
Upozornit na
guest
85 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Jirka Vejražka

Diky, clanek je opravdu zajimavy a tesim se na pokracovani. Mel bych ale prosbu – bylo by ve „vyukovych“ clancich mozne alespon priblizne dodrzovat zavedene standardy a konvence pro jmena funkci a promennych? V pythonu ze jmen typu „isCarWhichILo­okingFor“ nebo „listOfCars“ docela boli oci, tohle neni JavaScript ;-)

Diky!

Solitary

Nejsem Pythonista, proto se ptam… jake konvence jsou tedy ty spravne v Pythonu? Trosku mi prijde, ze spravna konvence je takova, ktera je pochopitelna na prvni pohled… ne takova, jakou diktuje jazyk. A tyhle Java(scriptove) nazvy jsou mnohdy dost vystizne.

Jirka V.

Konvence jsou právě v tom PEP8 – jména_metod_se_pí­ší_takhle. Docela užitečný nástroj pro tyhle účely je Pylint – http://pypi.python.org/pypi/pylint Ten člověka rychle postaví do latě :)

Jirka V.

Jak jsem to odeslal tak mě ještě napadlo… Ono to může vypadat jako zbytečná rýpačka = nemá co by zkritizoval tak se vozí po konvencích. Jenže Python je na konvencích postavený. Lecjaká důležitá konstrukce jako self u objektů, nebo _protected __private jsou taky jen konvence.

Python nikoho nenutí je dodržet, akorát o pak po vás nikdo nepřečte, a proto je v zájmu programátora samotného se jich držet. Konec konců samotný článek tím začíná, i v Pythonu se dá kód pěkně zprasit, stejně tak si ale můžete koupit novou LED telku a hodit jí z Nuseláku. Je to vaše volba.

přezdívka

__private není (narozdíl od _protected) jen konvence.

Jirka V.

Ja myslím, že to konvence v jistém smyslu slova přece jen je. Rozhodně ta proměnná či metoda není private ve smyslu jak to má Java.

I k metodě označné jako __private se dá celkem snadno dostat. Takže je to opět jen konvence, kterou ale respektuje i samotný interpret Pythonu a zabrání zavolání té metody přímo (AttributeError).

Jenže stačí to volání jen lehce upravit a…

Class Pokus(object):
   def __init__(self):
        self.__foo = 'neco desne duleziteho'

test = Pokus()

print test.__foo # vyhodi AttributeError, ale
print test._Pokus__foo # vypise 'neco desne duleziteho'
Inkvizitor

Od té doby, co v Javě zavedli Reflection, už to s tou ochranou také není, co to bývalo. Jinak bych řekl, že ta ochrana je v OOP obecně zamýšlena spíš jako konvence.

PMD

No, v pravém smyslu konvence to není, ale k přístupu k __private přes _MyClass__private vám stejně nic nebrání:)

ByCzech

Pylint má pro mě příliš false-positives keců, takže bych se jím do latě moc stavět nenechal…

Jirka Vejražka

Proto ma taky konfiguracni soubor, kde se da umravnit ;-)

ByCzech

To že mu zakážu upozorňovat na chyby, když je to jeho primární funkce, jen proto, že upozorňuje na chybu, tam kde chyba prokazatelně není, neříkám umravnění, ale vypnutí primární funkce. Řešení je chybu v takovém detekčním softu opravit a ne detekce vypnout, jinak ho nemá moc cenu používat.

Jirka Vejražka

Kdyz se mi z nejakeho duvodu nelibi jedno z 30 typu varovani, muzu ho „utlumit“. To jeste neznamena, ze dalsich 29 typu varovani je zbytecnych…

Inkvizitor

Prokazatelné a opakované falešné hlášky je možné řešit ad hoc, není nutné pylintu hned zakazovat hlášení určité skupiny chyb. Viz třeba http://www.logilab.org/blogentry/78354

petr

V Pythonu píšu několik let skoro na plný úvazek. Myslím že PEP8 je naprosto zbytečná hovadina, která se snaží jako součást komunity vynutit něco, co je individuální. Zrovna mě PEP8 vůbec nesedí (skoro v ničem: píšu tab místo mezer (zobrazený na 3 místa), zásadně nezačínám řádku, pokud nenásleduje odsazený blok, používám camelCase na proměnné místo _, které jsou delší, atd) a nevím, jak to souvisí s programováním. Přijde mi to, jako byste chtěl, abych při psaní měl na hlavě kulicha nebo něco podobného.

Jirka Vejražka

A kolik dalsich lidi musi takovyto kod cist nebo ho dokonce upravovat?

nakrev

Ja treba nemam problem se ctenim kodu ciziho cloveka. Staci mi, aby nepsal jako prase. Nemusi dodrzovat zadnou konvenci. Je mi jedno jestli pise camelCase, nebo podtrzitka, jestli dela mezery mezi }{()= , Jestli odsazuje 2,4,8 mezer. Dulezity pro me je, aby se toho stylu drzel a „nepreskakoval“.

Pokud na projektu dela vic lidi, tak bude urcite potreba dohodnout nejaky code style. Jestli to ale bude PEP8 nebo #endif to uz je na rozhodnuti/dohode.

V opacnem pripade pouziju vlastni hlavu. Pokud bude neco v ni, lide okolo budou stastni a usmevavi i bez PEPy.

To je muj nazor na tento obraz.

(Autor preferuje camelCase metody u pythonu a je mu jedno, ze z toho nekdo jinej jde do vrtule.)

Jiří Vraný

To je celkem legitimní názor. Pokud píše člověk pro sebe, klidně si to může psát v palindromickém haiku v mandarýnském dialektu.

Nicméně, pokud to má číst někdo další, nebo co víc, se podle toho učit programovat v daném jazyce, tak je lepší držet se konvencí platných pro daný jazyk. A že je má Python jiné než Java? To má i spoustu dalších věci…

ByCzech

To přirovnání k haiku v mandarýnském dialektu dost pokulhává, protože pro koho je nečitelná proměnná „TotoJeVystup­ZmehoObjektu“ místo „toto_je_vystup_z_me­ho_objektu“ nemá vůbec na to číst a pochopit algoritmy a další věci v takovém zdrojáku.

Ale to je jen můj subjektivní názor, protože číst takové základní věci mi nedělá potíž v žádném jazyce, se kterým jsem se setkal…

Jirka Vraný

Haiku nesmíte brát tak doslova. To byl pokus o vtip :) Celkem vzato si nemyslím, že je potřeba dělat z toho téma roku. Najdou se i velké Python projekty, které camelCase používají, například PySide (PyQT). Má to tam svůj důvod – aby API bylo stejné jako v C++. Nicméně si stojím za tím, že výukové články o Pythonu by PEP8 ctít měli a jsem rád, že to autor článku tady v komentářích sám uznává.

Kenny

Díky pěkný článek!

CamelCase je hodně používané a rozhodně ne nepřehledné ;) S javascriptem jako takovým už nemá vůbec nic společného. Je to asi spíš o tom na co je člověk zvyklí nebo o tom jakou máš nastavenou štábní kulturu v teamu.

Když se podíváš na dokumentaci pythonu ( http://docs.python.org/tutorial/classes.html#a-word-about-names-and-objects ) tak uvidíš že borci taky používají CamelCase ( class MyClass ).

Takže jestli tě z toho bolí oči tak jenom proto že jsi zvyklí na_něco_jiného_;)

Jirka Vejražka

Ono to mozna bude tim, ze pro class je CamelCase doporuceno, zatimco pro funkce a promenne ne :)

Kenny

To určitě stačí vyhledat Python Coding Standards ( http://www.python.org/dev/peps/pep-0008/ ). Pořád to ale nemění nic na tom že CamelCase rozhodně nevychází z javascriptu ;)

Piitak

Predpokladam, ze v nasledujicim prikladu doslo k prohozeni radku:

obj = None
for item in listOfCars:
    if item.isCarWhichILookingFor():
        obj.unlockTrunk()
        obj = item
        break
Martin Hassman

Opraveno, děkuji.

had

Myslím, že by nebylo na škodu, kdyby čtenář věděl o verzi Pythonu, pro kterou jsou příklady napsány.

daks

Taky se přimlouvám, já chápu článek jako popis toho, co je v Pythonu novýho od verze 3. Ono to z článku v podstatě vyplyne, ale hodilo by se to napsat někde v úvodu.

Lada

Děkuji za zajímavé a poutavé informace. Člověk se učí pořád. Díky a těším se na pokračování.

emko

Díky za zajímavý článek. Sice jsem primárně (= v práci) .Neťák, ale i tak se hodí. Těším se na pokračování.

zeitung

prestal jsem cist po hlasce „V dnešní době však není podstatné mít efektivitu neustále na paměti.“

Lada

Ano, v jazyku C nebo assembleru máte vše v rukách, včetně režie paměti. Ale třeba vypsat výskyt všech slov ze souboru není tak jednoduché jako použit např. kód:

import re
m = re.compile('(w+)')
slova = set()
for radek in open('soubor'):
  slova.update(m.findall(radek))
print slova
Ales Zoulek

Opravdu bych byl rad, kdyby autor v prikladech kodu dodrzoval pep8 a tedy psal jmena metod a funkci podtrzitkovou­_notaci. Zvlast pokud ma ambici ukazovat, jak v Pythonu psat *profesionalne*.

Nejde o zadne bezucelne rypani. Naopak, Python si zaklada na dodrzovani urcitych konvenci a nedodrzovani spravneho pojmenovavani je minimalne stejne nevhodne jako psani dlouhych necitelnych onelineru, ktere autor sam (opravnene) kritizuje.

A koneckoncu osvojeni pep8 je schopnost, ktera se v profesionalnim python vyvoji hodi mnohem casteji jak znalost else bloku ve while cyklu.

Neseznamak

Pf, PEP8, bud rad, ze tam nepise #endif .

Nevidels Python kod, jak ho pisi profesionalove?

https://github.com/seznam/sklik-api-python-client/blob/master/sklikapi/client.py

hejhula

Dobře jsem se zasmál, děkuji za upozornění. :-)

ornyx

Konvence jsou prima vec, ale ja napriklad pri psani veci v Pythonu pouzivam zasadne javovskou (a vsude jinde pouzivanou) camel case konvenci (tohleJeJmeno­Funkce, JmenoTridy), protoze Python neni muj jediny nastroj (js, as3 a dalsi) a me treba podrzitkova konvence pride priserna, ale k cecku (ze ktereho asi pochazi) jsem pricichl jen letmo…

Neseznamak

Ano, ani Python neni muj jediny nastroj, ale respektuji konvence jazyka/prostredi, ve kterem delam.

Opacny pristup znemena, ze jsem tam vetrelcem.

Mimochodem, javovskou (***a vsude jinde pouzivanou***) svedci pouze o tom, jaka je vase definice slova vsude.

https://profiles.google.com/118074983456106867579

Klidne pouzivejte zasadne Javovskou konvenci vsude. Problem je v okamziku, kdyz bude clanek „Java profesionalne“ pouzivat coding style ala Cecko, Perl, nebo cokoliv co jde proti tomu, co se v Jave povazuje za spravne…

Rax

Za camel case normálně sekám ruce, tedy není pravda že je to všude jinde používané :-) To proto, že rozlišovat identifikátory pouze na základě velikosti písmen je zaručená cesta do záhuby a zdroj zcela zbytečných chyb.

emko

Vyjma Clojure (tam-se-identifikátory-píší-s-pomlčkami) jsem se snad nikde nesetkal s tím, že by se camelCase nepropagovala. Asi to záleží na tom, v jakých oblastech se člověk pohybuje ;-)

Riff

Díky za osvícení. Doteď jsem napsal kilometry kódu s camel-case konvencí a až díky vám jsem si uvědomil, že se v těch kódech vlastně nevyznám a všichni kdo je upravují taky ne. Ještě jednou moc díky, jdu to všechno zrefaktorovat.

Inkvizitor

V projektech, které jsem v Pythonu (v týmu) páchal, jsou stovky tisíc řádků a NIKDY tam nebyl problém ve špatné velikosti písmen. Camel case je naprosto rovnocenné podtržítkové notaci ve všech směrech.

MilanK

Občas se mi stane, že dospěju k následující konstrukci:

d = nacti_polozku()
while polozka_je_platna(d):
    zpracuj_polozku(d)
    d = nacti_polozku()

v C jde zkombinovat ten test platnosti a nacteni do jednoho:

while ((d = nactipolozku())
    zpracuj_polozku(d);

Nejde to zapsat v Pythonu take nejak jednodusseji, aby se to cteni nemuselo zapisovat dvakrat? (V uvedenem prikladu mam na to funkci nacti_polozku, ale obcas je to treba jen slozitejsi vyraz, kvuli kteremu nenadefinuji dalsi funkci, ale proste ho tam dvakrat opisu). Napada mne jedine nasledujici, ale to je neprehledne:

while True:
    d = nacti_polozku()
    if not polozka_je_platna(d): break
    zpracuj_polozku()
Jirka V.

Bohužel to nejde. Je to vlastnost – http://docs.python.org/faq/design.html#why-can-t-i-use-an-assignment-in-an-expression .

Záleží to hodně na povaze toho objektu d. Nešel by mu například nadefinovat iterátor, třeba pomocí metody __iter__ ? Pak by while nebyl potřeba a mohlo by to být prosté

for polozka in d:
zpracuj_poloz­ku(polozka)

Havri

Mělo by to jít přepsat na for pomocí funkce iter. http://docs.python.org/library/functions.html#iter

Havri

Myslím to takto:

for d in iter(nacti_polozku, None):
    zpracuj(d)

Jediným předpokladem je, že funkce nacti_polozku musí, pokud už dojde „na konec”, vrátit None (nebo jinou zvolenou hodnotu).

Neseznamak

Jedniduchost a citelnost, zalezi co si clovek vybere ,)

Nevim co presne znamena polozka_je_platna, protoze v tom Ccku tak nejak neni. Jestli to jenom znamena ze uz se nevratilo nic, tak staci

map(zpracuj_polozku, iter(nacti_polozku))

Pro hodne funkci to pujde i bez toho iter.

Havri

Jen bacha na to, že v Pythonu 3 vrací map iterátor, takže kód se neprovede okamžitě. Pokud to dále nezpracuji, nic se vlastně neprovede.

MilanK

Děkuju za návrhy, například o druhé formě iter() se dvěma argumenty jsem vůbec nevěděl. Obecně je asi řešením mého dotazu nějaká forma iterátoru, ať už přes iter() nebo podpora iter protokolu v používaném objektu. Vlastně to popisují na tom http://docs.python.org/faq/design.html#why-can-t-i-use-an-assignment-in-an-expression.

A to, že map() vyrábí konečně iterátor (nesouvisí vůbec s mým dotazem), mě snad přiměje začít používat Python 3 :-)

had

Korektura prehledla spatne uvozovky!!! Neni-liz pravda. Autor byl zrejme za skolou :)

had

Pokud nedas do uvozovek celou vetu, pak nezahrnuj tecku do uvozovek.

ok3

Díky, vždycky se těším, když si v diskusi pod článkem o programování promrskám i češtinu!

ByCzech

Já jako ternární operátor používám (a nejen já) obvykle konstrukci:

(výraz1, výraz2)[podmínka]

Trik v článku je pro mě novinka…

Havri

V článku zmíněné konstrukce (přes andy a ory a if else) běžně vídám, ale tohle vidím fakt poprvé. Připomíná mi to konstrukci

cena = '100'
mena = 'Kc'
ukazMenu = True

cena += mena * ukazMenu

Ve smyslu

if ukazMenu:
    cena += mena
ByCzech

Mi to nečitelné nepřijde, asi je to subjektivní záležitost a zvyk. V céčku je to:
Podmínka ? VýrazKdyžPravda : VýrazKdyžNepravda
V Pythonu je to přesně pozpátku v tomto triku, to je jediná věc, kterou jsem si musel zapamatovat.
Víc lidí, víc chutí…
Každopádně díky za článek.

Raskal

Pozor na specificka chovani vyhodnoceni ternarniho operatovu v kontrukci and-or:

In [719]: def a(x):
…..: print x
…..: return x
…..:

In [720]: (a(1), a(2))[1>2]
1
2
Out[720]: 1

In [721]: 1>2 and a(1) or a(2)
2
Out[721]: 2

Osobne pouzivam tvary (<podm> and <then> or <else>) resp. (not <podm> and <else> or <then>) v pripade, kdy bool(<else>) == False a zaroven bool(<then>) == True. Dalsim duvodem je zbytecna konstrukce pametove struktury tuple.

Nejlepsi je nasledujici zpusob (ostatni jsou zrejme hacky; ja osobne velmi preferuji podminku na zacatku vyrazu a ne nekde uprostred):

In [722]: a(1) if 1>2 else a(2)
2
Out[722]: 2

In [723]: a(1) if 1<2 else a(2)
1
Out[723]: 1

blizz

to vpodstate ani neni trik, if then else je proste normálny výraz, preto v nom ternarny operator nema zmysel… neviem ako v pythone ale vo funkcionálnych jazykoch je vsetko výraz.

zzzzzzzzz

…python a profesional v jedne vete mi prijde usmevne :-D
Python na rychle prototypovani, rychlou vypomoc s jednorazovym problemem nebo podobne – Ano
Python na aplikace ktere budou cteny vic lidmi vic nez jednou, a ktere nejsou trivialni rozhodne NE

Denne vidim problemy zpusobene chybami ktere se projevi az pri behu, ruzne formatovani ruznych lidi atd… peklo.

Na druhou stranu, je dobre ze lidi se uci dalsi jazyk, takze v serialu jen dal…

Neseznamak

„ruzne formatovani ruznych lidi“

Tyjo, tak zrovna z jazyku co znam mi tohle prislo v Pythonu jako nejmensi problem, at uz to porovnam prakticky s cimkoli co me napada.

Ktere jazyky to maji vyresene lip?

Raskal

S kazdym „parametrem“ jazyka se musis nejak vyrovnat. Ani silne typovany jazyk se vsema moznyma kontrolama pri prekladu te pred runtime chybou nezachrani. Python poskytuje daleko mensi pocet radku kodu o stejne funkcnosti a maximalni svobodu manipulace s prostredim. Kdyz vis jak ho pouzivat a nezastavas dosavadni nazor, tak na tom muzes vydelat. Tim nerikam nic o nazorech zakaznika. Python neni pro kazdeho a nekdo ma ve svem kodu rad 50% vaty jednovyrazovych metod urcenych k uspokojeni kompilatoru napriklad ruznymi fasadami pro preskladani parametru a jejich default hodnot. Ja ne a tak rad pouzivam Python.

Radek Miček

Ani silne typovany jazyk se vsema moznyma kontrolama pri prekladu te pred runtime chybou nezachrani.

Některé jazyky ano.

Python poskytuje daleko mensi pocet radku kodu o stejne funkcnosti

Myslím, že program v Haskellu může být kratší než program v Pythonu,
a to při zachování funkčnosti.

Raskal

[Některé jazyky ano.]

Zadne. (Neobskurdni standardne pouzivane programovaci jazyky.)

[Myslím, že program v Haskellu může být kratší než program v Pythonu,
a to při zachování funkčnosti.]

Neni treba chodit az k Haskelu. Perl to zvlada taky napriklad diky automatickemu vytvareni datovych struktur. Plati se za to zase treba prehlednosti a srozumitelnosti kodu. Nerikam, ze je na tom Python s delku kodu nejlepe, neni. Zato je to skriptovaci jazyk s vykonnosti blizici se napriklad kompilovane Jave (pypy – JIT, RPython a moznost kompilace, …) a pritom neni v kodu potreba definovat v podstate nic, co definovat nechci.

Radek Miček

Perl to zvlada taky napriklad diky automatickemu vytvareni datovych struktur.

Jenže tyto tzv. dynamicky typované jazyky mají velmi slabý typový systém, který vám s korektností programu nijak nepomůže. Haskell jsem uvedl právě kvůli jeho silnému typovému systému.

Raskal

[…s korektností programu nijak nepomůže…]

Je otazka, zda s tim ma a muze pomoci (duck typing). Nutnost svazovani trid pres interface jen proto, abych s nimi mohl dale pracovat na abstraktnejsi urovni, to mi prijde dost draha vlastnost predevsim v ranne fazi vyvoje. Pokud tyto dodatecne informace nemusim (mohu, ale nemusim) specifikovat, mohu se vice zamerit na vlastni reseny problem. Dalsi upresnovani informaci v kodu znamena dodatecnou davku informaci, kterou je nutne dale udrzovat s hlavnimi zmenami. Tuto praci za mne muze udelat stroj.

[…jsem uvedl právě kvůli jeho silnému typovému systému.]

Rozumim.

Honza Kral

Uz ponekolikate prosim autora pod jeho clankem aby respektoval jazyk ve kterem
pise. Drive jsme se jeste mohli hadat zda to je dulezite kdyz clanek mel udajne
byt o hezkem kodu obecne a Python byl jen pro ilustraci; to uz ale tentokrat
jasne neplati.

Kod v clanku opet obsahuje zakladni chyby proti stylu (pep-8) a bezpecnosti
(osetrovani chyb) ktere rozhodne nejsou nad ramec tech par radku ktere se nam
snazi autor ukazat.

Zacatecnikum by mozna mohlo vice pomoct informace o tom jake ma Python datove
struktury, jak pracuje s promennymi, jaky je rozdil mezi == a is nebo proc je
dulezite vedet jaka datova struktura je immutable. Vedet ze cyklus v pythonu
muze mit blok else je sice cool, ale v realnem svete profesionalniho
programovani to zas tak relevantni neni a uz vubec ne neco co by patrilo do
oblasti znalosti kterou musi kazdy programator znat.

Abych jen nekritizoval tak rad nabidnu sve sluzby pokud bude autor chtit
zkonzultovat kod ci clanek jeste pred vydanim. Myslim si ze Python je skvely
jazyk ktery se hodne rozmaha a ktery ma siroke uplatneni od drobneho
skriptovani, pres webove aplikace az po implementaci rozsahlych systemu, byla
by skoda kdyby si nekdo delal obrazek o Pythonu a programovanim v nem na
zaklade clanku ktere neodpovidaji realite.

Martin Hassman

Honzo, pokud bude Michal souhlasit, klidně ti další díly pošlu předem k nahlédnutí.

emko

Hm, ono tento článek asi není pro začátečníky.

Upřímně, já osobně python používám minimálně, převážně na jednorázové věci (= napsat a zahodit; tedy přesně pro ten případ, kdy „command line Jedi“ použije gerp, awk a sed) a jen tam, kde je nainstalovaný (jinak mám smůlu a musím použít Brainfu… pardon, Perl). Myslím, že takových jako já, je mezi uživateli Pythonu hodně. A předpokládám, že i mezi čtenáři tohoto článku.

Je mi celkem jedno, jestli autor dodržuje best practices nebo ne. To patří do produkčního kódu, ale bylo by celkem zbytečné u pár ukázkových řádků. Podle vyznění je článek zaměřen na pokročilejší uživatele, kteří chtějí na první pohled vidět, co chtěl autor říci. Ne na začátečníky, kterým je potřeba vštěpovat základní pravidla.

Honza Kral

Ahoj, tykat si urcite muzem ;)

v tom pripade se tesim na dalsi dily. Moje nabidka stale trva, ja bych rad videl neco na tema implementace zakladnich datovych struktur, dekoratoru, deskriptoru a metaclass. V techto tematech panuje spousta mytu a dogmat ktere neodpovidaji realite a pritom se jedna prave o nekolik malo mist jejichz pochopeni otevre cloveku uplne cely Python a nic ho v tom jazyce uz dal neprekvapi.

Pokud by se melo jednat o prakticke rady ktere clovek muze pouzit a mene o teoreticke znalosti, rozhodne bych doporucil pruchod knihovnami itertools a collections kde jsou perly ktere uz jsem mnohokrat videl naimplementovane v kodu zcela zbytecne prave proto ze si lidi nejsou vedomi toho ze tuto praci za ne jiz odvedl nekdo mnohem chytrejsi :)

Amatér

Toto je hodne, hmm, blbý spôsob:


for item in listOfCars[::-1]:
# Do something...

Tento kód najprv zbytočne celý zoznam otočí do dočasnej kópie, ktorú po skončení cyklu zahodí.

BS-Harou

A já jako javascriptař jsem třeba rád, že článek dodržuje JS konvence místo nějakýho pep8 :) Pro mě osobně je to tak daleko čitelnější….

PMD

A vlastně taky dodržuje Java konvence, takže dotneťák by měl být po právu dotčen, že to nejde číst, protože metody nemají první písmeno velký:)

blizz

dodneťákovi je to jedno, ja sa skor prihovaram za syntax highlighter.

emko

Java a C# konvence se pokud vím moc neliší…

blizz

v C# sa pouziva u public members PascalCase, v Jave camelCase.

emko

Těch rozdílů je víc, tohle je ten na první pohled nejviditelnější.

Čelo

Děkuji za článek a těším se na další.

kthxbye

nebyl nahodou ternarni ? ternalni zni stlasne ;-)

hejhula

Posledních 7 let se živím výhradně programováním SW v pythonu (s vyjímkou pár desítek kilobajtů .sh a .sql) a článek je podle mne špatný, nebo alespoň špatně pojmenovaný.
Měl by se jmenovat spíše tipy a triky v pythonu a mělo by být dodané varování, ať se jim v profesionální praxi vyhýbáte!

Protože poté, co s vaším nepřehledným kódem zacvičí vaši kolegové, kteří ho budou chtít v časovém stresu změnit, se vzteky po*erete.

Pro týmovou práci v byznysu, kde nevíte, jakého matláka vám manažer přiřadí jako kolegu na projekt, JE KLÍČOVÉ PSÁT STUPIDNĚ JEDNODUCHÝ KÓD, je-li to vůbec možné.

Třeba ternární operátory jsou na hraně a často nestojí za ušetřené 2-3 řádky. A vůbec snad všechny triky, jak výraz zkomplikovat na méně řádků, jsou ŠPATNĚ. Váš nečitelný kód nebude upravován, ale bude v určitých situacích „oběhnut ifem“ nebo reimplementován, s příslušnými dopady na rychlost a spravovatelnost programu.

Prasit tak, jak to bylo ukázané v článku, můžete i v byznysu. Ale neříkejte tomu profesionalita. Tak si můžete dovolit psát nedůležité části prototypu.

Raskal

Ctivost a srozumitelnost produktu je prvni v rade. Z tohoto duvodu je potreba, aby samotny kod mel sam o sobe optimalni vypovidajici hodnotu (samodokumentujici nazvy promennych, funkci a trid, proste vseho krome klicovych slov, kde si sam volim nazev) o tom, jak byla jeho funkce zamyslena. Zbytek je treba davat do dokumentacnich retezcu a do jednoradkovych komentaru tam, kde se provadi jakasi celistva operace (mentalne celistva).

Shodou okolnosti me Python take zivi cca 7 let a dodrzovani techto konvenci mi uz mnohokrat pomohlo od opakovani vlastnich chyb. Dokonce si v kodu nechavam zakomentovana zaludna zdanlive spravna reseni situace, abych vedel, ze jsem tuto chybu jiz jednou udelal, doplatil na to a neopakoval se. Pokud bude program takto dobre napsan, muzete si v nem dovolit i pokrocile vyjadrovani.

Ternarni vyraz je nebo bude krome poskytnute moznosti vyjadreni take vniman JITem jako moznost k optimalizaci.

Kolega znaly analyzy problemu, ktery neni schopen pojmout v souladu s analyzou projektu dobre napsany a komentovany kod, je pro mne bud liny ho pri cteni vnimat nebo je jednoduse neschopny a oboji znamena, ze neodvadi kvalitni praci. Problem nastava tam, kde nema kod dostecne vypovidajici schopnost na sebe prozradit co ma ktera pasaz delat. Takoveho kodu je dnes vetsina a pri stresujicich situacich je pak mene narocne jej obejit nez resit rebusy na ktere neni prave ted cas.

Python, ackoliv smeruje k jednoduchosti, poskytuje velmi pokrocile moznosti programovani. Pokrocilym programovanim nemyslim programovani jen pro zapis (cili „fuj, tohle se fakt neda cist“). Myslim tim napriklad pouziti metatrid, generatoru a uzaveru, kde si kolega neznaly ternarniho operatoru zrejme neskrtne. Pouzivat se maji tam, kde je to vhodne pouzit, tedy vetsinou na core casti a stale pamatovat na to, ze vhodne neznamena vzdy nutne. Zaroven maji mit tyto core casti jasne hranice a byt male, aby se pripadne nedodelky a nejasnosti nesirily dal pres lidi v tymu a jejich odpovednosti.

Klerik

dobrý den, můžete mi napsat na mail klerik_na_klerik.cz ? Mel bych par dotazu ohledne profi pyhonu, diky.

Klerik

Dobrý den hejhulo :), mohl byste mi napsat na mail klerik_na_klerik.cz … mel bych par dotazu ohledně profi pythonu. Díky.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.