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

Zdroják » Různé » Python profesionálně: co jazyk nabízí

Python profesionálně: co jazyk nabízí

Články Různé

V předchozích dílech tohoto seriálu jsme si ukázali spoustu syntaktických tipů. Dnes už necháme syntaktické tipy být a posuneme se trochu dál: vestavěné funkce, užitečné metody slovníku, na co si dát pozor u defaultních parametrů funkce, zajímavé moduly a další.

Iterace instančními proměnnými

Nedávno jsem narazil na problém, že mám něco jako slovníkovou instanci, ale přesto to slovník není. Tedy mám instanci s key-value hodnotami, ale neexistují metody items či iteritems. Konkrétně se jednalo o instanci Values, kterou vrací metoda parse_args z instance třídy OptionParser. Raději zopakuju technicky:

from optparse import OptionParser
parser = OptionParser()
# ...
options, args = parser.parse_args()

options # <Values at 0xb730b46c: {...}>
options.items() # AttributeError

# `options` je neco jako:
class C:
    def __init__(self):
        self.arg = 'val' # Nejaky argument z prikazove radky.
options = C()

Je to modul, který (hezky) pomáhá rozparsovat argumenty z příkazové řádky (nutno podotknout, že od Pythonu 2.7 je označen za deprecated a nahrazuje ho argparse). Jak je vidět, svádí to k tomu, že se jedná o slovník a přesto to slovník není. Nyní, když bych chtěl proiterovat všemi proměnnými, které byly nastaveny (ať přes příkazový řádek nebo defaultně), … tak nemám jak, poněvadž pro to není žádná metoda. Proměnné jsou nastaveny jako instanční proměnné a žádné jiné se tam nepletou, takže by šla použít speciální proměnná __dict__, jenže to spíš vypadá jako hack.

options.__dict__ # {...}

V Pythonu existuje built-in funkce vars, která bez parametru dělá totéž, co locals. S parametrem (jakýkoliv objekt) však vrací právě ten zmíněný slovník toho objektu, tedy to samé, co příkaz výše.

vars(options) # {...}

Mně osobně se více libí tato varianta. Nyní už můžu procházet nastavené parametry z příkazové řádky…

for key, val in vars(options).iteritems():
    # Do some stuff.

Chybějící klíče

Mějme problém: potřebujeme v nějakém textu spočítat početnost slov. Třeba abychom si ověřili, že náš textař splnil podmínky pro PR článek. :-) Můžeme na to jít jednoduše:

words = 'hello world hello python'.split(' '):

count = {}
for word in words:
    if word not in count:
        count[word] = 1
    else:
        count[word] += 1

Ale je to takové nemastné neslané. Chtělo by to vylepšit a pomoct může defaultdict z modulu  collections.

from collections import defaultdict

count = defaultdict(int)
for word in words:
    count[word] += 1

Hned je o podmínku méně a tím i menší pravděpodobnost potenciální chyby. Bohužel nám tento speciální slovník nepomůže ve složitějších situacích, protože jako parametr přijímá pouze callable objekt. Například pokud bychom chtěli počítat od jedničky a ne od nuly, bude to tak trochu hloupé, ale lze to. Přijdete na řešení sami dřív, než se podíváte o kousek níže?

count = defaultdict(lambda: 1)

Například zde se hodí lambda funkce bez parametrů (o lambda funkcích jsme psali posledně). Jenže není to úplně šťastné (= čitelné) řešení, a proto nekončíme a ještě to trochu poladíme.

Poladíme to naším vlastním speciálním slovníkem obohaceným o speciální metodu, o které se nemluví a nepíše. V dokumentaci na ni téměř nenarazíte; lze ji spatřit pouze u dokumentace zmíněného defaultdict u nebo v článku What’s New in Python 2.5, jinak nikde. Ostatní speciální názvy metod jsou k nalezení v dokumentaci se speciálními metodami. Jedná se o speciální metodu  __missing__.

class MyDict(dict):
    def __missing__(self, key):
        return 1

count = MyDict()
for word in words:
    count[word] += 1

Od Pythonu 2.7 lze pro tento konkrétní případ jednoduše použít třídu Counter z modulu  collections.

Defaultní hodnoty slovníku

Na předchozí tip navážu více méně podobným tipem. Ten už jsem sice popisoval v dřívějším článku o optimalizacích v Pythonu, ale opakování je matka moudrosti… Jde o to, proč dělat věci složitě nejen pro nás, ale i pro server. Místo

d = {}
if key not in d:
    d[key] = 0
d[key] += 1

d = {}
if key not in d:
    d[key] = []
d.append(element)

lze jednodušeji napsat

d = {}
d[key] = d.get(key, 0) + 1

d = {}
d.setdefault(key, []).append(element)

Vidíte to? Předchozí tip můžeme řešit ještě jinak. Všechno lze řešit různými způsoby a je jen na vás a na okolnostech, který je v danou chvíli nejlepší. Já jen ukazuji možnosti.

Zpět k ukázce: První metoda slovníku, get, zkusí najít ve slovníku klíč z prvního parametru (a hodnotu toho klíče vrátí) a v případě neúspěchu se vrátí hodnota předaná v druhém parametru. Druhá metoda se chová podobně, jen v tom rozdílu, že v případě neúspěchu navíc nový klíč vytvoří a nastaví. Z ukázky je patrné, která metoda se k čemu více hodí.

Defaultní parametry nemusejí být kamarádi

Python, stejně jako spousta jiných jazyků, umí definovat parametry s přednastavenou hodnotou. Je to velmi dobrá funkčnost, ale v Pythonu si s ní můžete nevědomky natlouct nos. Podívejte se na následující ukázku:

def foo(x=[]):
    x.append(1)
    print x

foo()
foo()
foo()

Co myslíte, že se stane? Myslíte, že se třikrát vytiskne na standardní výstup seznam s jednou položkou a to číslem jedna? Tak to jste na omylu! V prvním zavolání se vytiskne seznam s jednou položkou, jak je očekávatelné. Druhé volání však už seznam s dvěma položkami, obě budou jedničky. Třetí volání už se třemi a takhle by to pokračovalo klidně dále.

>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

Proč tomu tak je? Nu proto, že se defaultní hodnota parametru zkonstruuje při vytváření funkce. V průběhu programu zůstává vytvořená instance stejná – stále stejná reference na stejnou instanci. Samozřejmě pokud při volání funkce předáme nějaký parametr, tak se to nestane; stejná reference se předá pouze při volání bez parametru. A díky tomu lze vygenerovat velmi zajímavé chyby a tím i strávit příjemné večery jejich hledáním. :-)

Jelikož v Pythonu jsou jedna jednoduchá pravidla, která jsou aplikovaná na všechno (místy mírně upravená, samozřejmě), je to tak logické, i když se to nemusí na první pohled zdát. Obrana proti tomu je velmi jednoduchá a existují prakticky dvě možnosti.

První možností je u neprimitivních datových typech používat jako defaultní hodnotu hodnotu None a až na začátku těla funkce si vytvořit potřebnou instanci:

def foo(x=None):
    if x is None:
        x = []
    x.append(1)
    print x

foo() # [1]
foo() # [1]
foo() # [1]

Bohužel tohle řešení má dvě vady. Jedna je ta, že None hodnota může mít speciální význam. Šla by sice použít jiná hodnota, třeba nějaký vlastní objekt EMPTY_VALUE = object(), ale stále to není pravé ořechové. A druhou vadou na kráse je lhaní v našeptávačích – až po přečtení nápovědy bych se dozvěděl (pokud existuje!) skutečnou defaultní hodnotu místo nesprávné None hodnoty.

Tyto vady řeší druhé řešení, které definici ponechává zachovanou, a na začátek těla funkce musíme přidat trochu jiný kód a to kopii instance. U datových typů typu seznam nebo slovník (jiné bych ani jako defaultní hodnotu nedával) to je primitivní:

def foo(x=[]):
    x = list(x)
    x.append(1)
    print x

foo() # [1]
foo() # [1]
foo() # [1]

Trochu jiný switch

Jak všichni jistě víme, switch v Pythonu není. Opravdu, neukážu vám u tohoto tipu nic takového. On totiž ani není potřeba, posteskl jsem si nad jeho neimplementací za čtyři roky pythonování snad jen jednou. Chtěl bych však ukázat, že lze v Pythonu dělat opravdu téměř všechno, klidně switchnout metody za běhu…

class C(object):
    def __f(self):
        print 'calling of f'

    def f(self):
        print 'first calling of f'
        self.f = self.__f

c = C()
c.f() # first calling of f
c.f() # calling of f
c.f() # calling of f

Tím chci poukázat na to, že v Pythonu je téměř vše reference na nějaký objekt a ta reference lze kdykoliv zaměnit. Python skousne hodně, zkuste experimentovat. Samozřejmě ale ne každý experiment se hodí do produkčního kódu. Například v konstruktoru vytvářet jinou instanci (ano, to také lze) je dle mého názoru už za pomyslnou hranicí; musely by být hodně dobré argumenty, aby se mi taková věc líbila.

Kde se tohle konkrétně může hodit, ještě ukážu.

Matematické operace s množinami

V běžném programování to není tak běžné, ale stejně se občas hodí využít nějaké ty množinové operace, které nás učili ve škole. Pokud jste se s takovou situací už někdy setkali, musíte vědět, že pomocí obyčejného seznamu nebo tuplu to nelze provést. Řešení přináší až datový typset (či frozenset, obdoba pro tuple) nebo česky množina.

a = set([1, 2, 3])
b = set([3, 4])

a.union(b) # set([1, 2, 3, 4])
a.intersection(b) # set([3])
a.difference(b) # set([1, 2])
b.difference(a) # set([4])
a.symmetric_difference(b) # set([1, 2, 4])

Kdo umí dobře anglicky (nebo alespoň matematické výrazy), nebude mít problém. Python se však snaží práci vždy ulehčovat, proto existuje i pohodlnější varianta pro nejazykovce:

a | b # set([1, 2, 3, 4])
a & b # set([3])
a - b # set([1, 2])
b - a # set([4])
a ^ b # set([1, 2, 4])

Ukázané metody mají i své sourozence s příponou _update (až na union, který má pouze update). Z názvu je zřejmě patrné, že příkaz nevrátí novou množinu, ale upraví instanci, ze které je metoda volána. A i pro tyto metody existuje pohodlnější varianta, stačí přidat rovnítko.

a.update(b)
a |= b

a.intersection_update(b)
a &= b

a.differenece_update(b)
a -= b

a.symmetric_difference_udpate(b)
a ^= b

Mimochodem v Pythonu 3 se množina dá zapsat pohodlněji pomocí složených závorek. Od slovníku se to liší absencí klíčů.

a = {1, 2, 3}
b = {3, 4}

Ale pozor! Kvůli zpětné kompatibilitě zůstávají prázdné chlupaté závorky stále prázdným slovníkem. Prázdná množina se musí deklarovat postaru.

a = {1, 2} # Mnozina.
b = {} # Prazdny slovnik.
c = set() # Prazdna mnozina.

Debug složitých struktur

Poměrně často se mi stává, že potřebuji zdebugovat nějakou část kódu, kde se pracuje s opravdu složitými strukturami. Samozřejmě si vypomáhám zpětnými lomítky (které v Pythonu 3 už nenalezneme, ale to nevadí, protože to je pouze alias pro built-in funkci repr) a obyčejným  print em.

>>> repr(var)
"[{'username': 'admin', 'rights': ('create', 'update', 'list', 'detail'), 'surname': 'Admin', 'id': 1, 'name': 'Admin'}, {'username': 'user', 'rights': ('list', 'detail'), 'surname': '', 'id': 2, 'name': 'User'}]"

V této struktuře se dá ještě dobře zorientovat a mohl by repr postačovat, jenže stačí někde přidat další zanořený objekt a už to začne být těžké pro čtení. A hlavně těžké zjistit, co v tom chybí (nebo přebývá) a způsobuje nějakou chybu. Je možnost si výpis jednoduše zkopírovat do chytrého editoru a zformátovat do „JSON Beautify“, ale s Pythonem je jednodušší způsob díky modulu pprint:

>>> import pprint
>>> pprint.pprint(var)
[{'id': 1,
  'name': 'Admin',
  'rights': ('create', 'update', 'list', 'detail'),
  'surname': 'Admin',
  'username': 'admin'},
 {'id': 2,
  'name': 'User',
  'rights': ('list', 'detail'),
  'surname': '',
  'username': 'user'}]

Nyní se to čte mnohem pohodlněji. Za zmínku také stojí, že lze předat parametrem stream na který se má výpis přesměrovat.

Šmrnc pro konzolové aplikace

Řekl bych, že Python je velmi vhodným jazykem pro konzolové skriptíky (samozřejmě záleží hlavně na preferencích a zkušenostech). Když už se ale Python použijete, zamyslete se nad využitím modulu readline, který uživatelům zpříjemní zadávání vstupu, hlavně opakovaného. Konkrétně pomáhá s historií, tedy opětovným použitím vstupu bez potřeby ho znovu celý napsat. Historii lze i ukládat a zase načítat. Více info v dokumentaci.

import readline

while True:
    in_ = raw_input(': ')
    if in_ == 'q':
        break

Předcházející ukázkou si můžete funkčnost jednoduše vyzkoušet – při zadávání vstupu v druhém a dalším cyklu zkuste stisknout šipku nahoru. K tomu lze rovnou přidat modul rlcompleter, který se spojením s readline dokáže našeptávat po stisknutí klávesy tabulátor (známé z příkazové řádky). Přesněji se jedná o našeptávač pro pythoní interaktivní interprety. Zkuste:

>>> import readline
>>> import rlcompleter
>>> readline.parse_and_bind("tab: complete")
>>> # ted zkuste programovat a vyuzivejte tabulator

Dobré doporučení je si do .bashrc přidat řádek export PYTHONSTARTUP=/home/me/startup.py a do tohoto souboru následující kód:

try:
    import readline
except ImportError:
    print('Module readline not available.')
else:
    import rlcompleter
    readline.parse_and_bind('tab: complete')

Tím se pokaždé před spuštěním interpretu Pythonu tento kód vyvolá a vždy bude aktivní našeptávač.

Závěr

Dnešním dílem jsme si řekli vše, co jsem chtěl sdělit za takové klasické tipy, které by měl určitě každý programátor v Pythonu znát, aby mohl využít co nejvíc z tohoto jazyka. Není to samozřejmě všechno, dalo by se toho napsat víc, ale to už nechám na vašem samostudiu. Příště se přesuneme k tipům, jak lze v Pythonu elegantně použít několik návrhových vzorů.

Dnešek opět zakončím několika odkazy k dalšímu studiu:

  • Doporučuju si projít seznam všech vestavěných funkcí, protože s jistotou narazíte na nějaké funkce, které řeší vaše každodenní problémy mnohem jednodušeji.
  • Není od věci si také projít, jaké všechny speciální metody lze použít.
  • Také je dobré si projít, co vše nabízejí vestavěné datové typy.
  • Než budete řešit nějaký problém, zkuste se podívat na seznam oficiálních modulů, jestli náhodou nějaký neřeší váš problém.
  • Python má vlastní hosting pro pythoní knihovny nazvaný jednoduše Python Package Index. Najdete tam téměř každou pythoní knihovnu a určitě byste tam měli dávat i ty svoje.

Komentáře

Subscribe
Upozornit na
guest
34 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
perl

Na pocitani slov je skoda startovat editor ;-)

perl -nae ‚END{print“$_:t$k{$_­}n“ for sort keys%k}$k{$_}+­+for@F‘

monitor

Perl na pocitanie slov? :-)

wc -w subor.txt

perl

wc -w dela neco jineho, shellovsky prikaz, ktery pocita cetnost slov, je uniq. Na to nelze rict nez RTFM.

perl

A jeho pouziti bude pomalejsi, protoze ta slova je treba nejdrive seradit. Muzete si to zmerit:

sed ‚s/ /n/g‘ | sort | uniq -c

MW

Presne takhle to vypadalo, kdyz se mi po klavesnici prosla kocka.

Riff

Tak ten byl dobrej :-D +1

PERL

Zrejme bude chytrejsi nez vy, kdyz umi programovat v perlu ;-)

tom

Pokud chci shell s našeptávačem, pouštím IPython. Je bohatší o opravdu úctyhodnou hromadu dalších funkcí, které jsou pro ruční psaní skvělé (copy, paste, editace příkazu v editoru, help přes ? a ??, barevné tracebacky atd atd).

Honza Kral

Naprosty souhlas, iPython je skvela zalezitost ktera toho umi neskutecne mnoho, od doplnovani na tabulator az po vzdalenou exekuci. Vice napriklad v http://pyvideo.org/video/640/ipython-python-at-your-fingertips

Whit

Mě zas baví bpython – http://bpython-interpreter.org/

dingo

je super si připomenout, že v pythonu máme tolik krásným funkcí a je dobré o nich vědět. Zatím nejlepší článek ze série Python profesionálně…

Laik

Tento zatím třídílný seriálek vypadá napsaný velmi fundovaně, je vidět, že autor opravdu ví, o čem píše. Pro mne (a asi nejsem sám) je to ale jako by psal švédsky.
Na linuxsoftu vycházel v letech 2005 – 2011 seriál o perlu – 149 dílů, krok za krokem.
Kéž by něco takového vzniklo i pro Py…

Předem, ale asi marně, děkuji.

KArol

Jak pisete, dobre napsano pro nekoho kdo to umi a chce si bud pripomenout co tam je nebo ukazat co lze. Proste pro lidi co v tom uz umi delat a chcou si zdelit na prikladech jde toto a jeste toto.

P.S. neklritizuju profesionalitu(au­tor dle clanku umi), ale pro nekoho kdo chce teprve zacit je to nepouzitelne.

Martin Hassman

Ale to je u seriálu zaměřeného na lidi, kteří Python již nějakou dobu používají, zcela v pořádku ne? Začátečník si stáhne kupříkladu český překlad „Ponořme se do Pythonu“, který je zdarma na http://knihy.nic.cz/ a může začít. Nebo využije některý se starších začátečnických tutoriálů, kterých je v češtině hned několik.

Laik

Díky za typ.

Skalimil Vuk

Ta kniha Ponořme se do Pythonu je výborná, vřele doporučuji. Líbila se i bývalému šefredaktorovi zdrojáku http://www.zdrojak.cz/clanky/python-3-uspesny-ponor/

V knihkupectví najdete Python 3 Výukový kurz od Marka Summerfielda. Jde od začátku a postupuje pěkně do hloubky. Také doporučuji.

Seriály pro začátečníky vycházely třeba i na rootu, ale jsou staršího data, je třeba s tím počítat.

jiri.vrany

Stačí nahlédnou na http://www.py.cz/TutorialyLiteratura – tam je zdrojů jak začít dost a dost. A výborný kurz základů programování a Pythonu je teď na http://www.udacity.com/overview/Course/cs101 – zatím asi nejlepší e-learning co jsem v životě viděl.

jiri.vrany

Že je prázdný list nevhodná výchozí hodnota, to ví každý kdo to zkusil a použil PyLint, ale aspoň jsem se dozvěděl proč. Díky.

osramek

Předpokládám, že v části „Defaultní hodnoty slovníku“ bylo na řádku 9 spíše zamýšleno:

d[key].append(e­lement)

Díky za článek!

Honza Kral

diky za clanek. Inspekce __dict__, at uz primo nebo pres vars() je pomerne nebezpecna zalezitost kdyz nevime uplne presne jak je dany objekt naimplementovany (a i potom ma sve problemy). Vtesina veci se da resit mnohem lepe a mnohem cisteji, v tomto pripade prostou inspekci parseru:

dict((o.dest, getattr(options, o.dest)) for o in parser.option_list if o.dest)

Ziskame si vsechny promenne ktere parse mel nadefinovat a z options ziskame jejich hodnoty. Pouzivame verejne API a mame jistotu ze nas kodu bude fungovat spravne, zadny zbytecny hack ktery se spoleha na vnitrni implementaci.

Dve reseni pro predavani listu jako parametru budou mit vyrazne jinou funkcnost, v nicem to nejsou ekvivalentni implementace! Nehlede na to ze vytvaret kopii parametru jen kvuli naseptavaci je pri nejmensim podivne. Od toho jsou v Pythonu docstrings abychom mohli popsat co metoda ci funkce dela. Kopirovani listu neni zadarmo.

Ad „Switch“: ano, jde to. Stejne jako jde zamenit objektu atribut __class__ za behu a zmeni mu to tridu. Je to ale dalsi z veci v tomto serialu ktere rozhodne nepatri do profesionalniho kodu, ani kdyz primhourim obe oci. A nedokazu si pro to predstavit zadny rozumny use-case ktery by nesel implementovat lepe.

A opet: jak to chcete testovat? Testovani je (spolu s citelnosti) jeden ze zakladnich piliru Pythonu a profesionalniho kodu presto spousta tipu popisovana v tomto serialu neniotestova a hlavne dramaticky zhorsuje testovatelnost (nehlede o citelnosti) kodu.

pavel
Ales Zoulek

Pokud ma serial za cil opravdu popisovat, jak psat Python *profesionalne*, mel by se drzet nekolika principu:

– Pouzivat public API, misto spolehani na vnitrni implementace
– Testovatelnost
– Citelnost

Podle toho by taky mely vypadat jednotlive rady a tipy. Pritom aspon polovina z clanku porusuje minimalne jedno z techto principu.

1] Seznam options je na parseru. Prochazet je pres vars() je spolehani se na nezname API a necitelne.

2] To, ze v Pythonu neni konstrukce „switch“ se typicky nahrazuje dictionary callables. Co s tim ma spolecneho monkeypatchovani vlastni tridy za behu??

3] Co je to za hack s readline, kdyz mame IPython? Proc???

Repr je dobry tip. Jen bych doplnil, ze byva uzitecne si metodu __repr__() definovat na vlastnich tridach – pomaha to pak pri praci s temito instancemi pri debugu v python konzoli.

Mnoziny se daji primo pres slozene zavorky konstruovat i v Python 2.7.

whiskybar

Kdyz jsme u toho Pythonu, prijdte se podivat na skutecne Python profesionaly z masa a kosti na dalsim, 13. Python/Django srazu, ktery probehne uz zitra, 18. 4. 2012 v Praze 5 na Smichove na adrese Ostrovkeho 38a!

Na tento vecer bude mobilni s (nejenom) Pythonem – Scala & Objective C. Vice informaci na http://lanyrd.com/2012/djangocs-april/

Martin Hassman

Dík, tady by to zapadlo, udělal jsem z toho zprávičku http://www.zdrojak.cz/zpravicky/ve-stredu-probehne-prazsky-python-sraz/

3socks

Dobré doporučení je si do .bashrc přidat řádek export PYTHONSTARTUP=/ho­me/me/startup­.py a do tohoto souboru následující kód

http://img837.imageshack.us/img837/6794/orwecoulduse.png

pepa

asi pomerne trivialni dotaz,ale nejsem pythonista,jen v prostredi aplikace ve ktere pracuji lze pouzit python jako scriptovaci jazyk…

alokace a pristup k pameti, potrebuji dynamicky vytvorit nejaky 3 rozmerny grid,radove tisice prvku na osach x,y,z pricems prvek bude nejaky class. v C-ku si alokuju pamet na x*y*z mych classu,klasicke 3rozmerne pole. chci to same udelat v pythonu,samozrejme to sice jde,ale vsechny postupy mi prisly zatgim jako drbani se levou rukou za pravym uchem.
jak se tahle vec dela klasicky po pythonovsku?

dik:-)

Honza Kral

Po pythonovsku nemusim nic alokovat, bud pouziju list (analogie array z jinych jazyku) nebo dict (=~ hashmap) pro sparse grid.

Zalezi na tom jak ten grid chces pak vyuzivat, jestli by nebyl nejjednodussi pouzit ten dict s tim ze jako index pouzijes tuple (x, y, z), takze:

grid = {}
grid[0,0,0] = object
grid[1,2,3] = dict
grid[x,y,y] = OtherClass

muzes pouzit i defaultdict z dnesniho clanku a alokovat tak jednotlive bunky lazy.

Pokud potrebujes ten grid nejak rezat tak bud muzes pouzit list obsahujici listy:

grid = [[[Class() for z in xrange(MAX_Z)] for y in xrange(MAX_Y)] for x in xrange(MAX_X)]

pripadne si muzu nagenerovat prazdny plochy list a klasicky prepocitavat souradnice:

# rychla inicializace velkeho listu
l = [None] * (MAX_X * MAX_Y * MAX_Z)

def get_y_column(l, zcord, ycoord):
wall_size = MAX_X * MAX_Y
temp_l = l[z*wall_size:(z+1) * wall_size] # z-ta stena kvadru
return temp_l[ycoord::MAX_Y] # kazdy MAX_Y-ty prvek, pocinajici ycoord == ycoord-ty sloupec

pro lepsi vykon lze oba slicy zkombinovat do jednoho a pro usporu pameti pouzit spise itertools:

from itertools import islice
def get_y_column(l, zcord, ycoord):
return islice(l, ycoord + zcoord + MAX_X * MAX_Z, (zcoord + 1) * MAX_X * MAX_Z, MAX_Y)

pozn: nekontroloval jsem jestli jsem nekde neprevratil poradi x, y, z – uvedeny kod slouzi pouze pro ilustraci moznych ristupu

pepa

diky moc,

jde mi o co nejprimnejsi pristup k bunkam,s tim ze rezy budou podstatne mene caste,ale budou.kompilovany kod mel radove miliony r/w operaci za sekundu,samozrejne se ocekava od pythonu mensi performance,ale aby to bylo maximalne python-optimalni:-) pri velikostech gridu jak jsem psal pujde o stovky MB/grid takze i nejkompaktnejsi pametova struktura by bodla:-) obejdu se bez vymozenosti jako variabilni velikost prvku atd.

Honza Kral

Tak nejprijemnejsi pristup k bunkam splnuje asi ten dict, je to nejjednodussi na primy pristup (O(1)) a clovek si nemusi pamatovat jak se ty listy vnoruji.

Co se pametove narocnosti tyka tak je to vcelku jedno – vsechno bude pracovat s referencemi ktere maji fixni velikost, u dict je index hash tuplu coz je jen cislo:

hash((1,2,3)) == -378539185

list v pythonu ma tu vlastnost ze musi obsazovat souvisly kus pameti coz muze zdrzovat pri alokaci a zvetsovani kdy se musi naalokovat vetsi misto + presunout stavajici data. U takhle velkych struktur uz to muze byt problem.

Nevim uplne presne jak je to s pameti u dictu, ale muj odhad je ze to bude pri nejhorsim stejne. Vice info: http://stackoverflow.com/questions/671403/memory-efficiency-one-large-dictionary-or-a-dictionary-of-smaller-dictionaries

dik

Ahoj, poradí mi někdo jak mám v metodě přiřadit novou hodnotu atributu obj? Toto mi nefakčí:

class abc():
def __init__():
self.is_alive= False

def zmena():
self.is_alive= True
return

def tiskni():
print(self.is_a­live)
return

ins = abc()

ins.tiskni()
False
ins.zmena()
ins.tiskni()
False

Přes global to nejde… Díky dik

Havri

Chybí ti tam self v definici metod.

class abc():
    def __init__(self):
        self.is_alive = False

    def zmena(self):
        self.is_alive = True

    def tiskni(self):
        print(self.is_alive) 
dik

sorry ,psal jsem to z hlavy ,ale v kodu self mam a presto to nefakci.
dik

Havri

Tenhle kód vypíše False, True. V Pythonu 2 i 3.

https://gist.github.com/2415523

dík

Ano,máte pravdu , vše funguje dle očekávání – měl jsem v kódu zamotanej modul „multiprocessin­g.Process“ ,který mě mátl.
Díky za Váš čas :-),Dík

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.