Podstawy Pythona. Przykłady z komentarzami na podstawie ćwiczeń z książki: Python i Django. Programowanie aplikacji webowych
http://www.webook.pl/b-12988,Python_i_Django_Programowanie_aplikacji_webowych.html



if show_output and foo == 1:
print 'Python i %s są numerem %d' % ('Django', foo)
#Python i Django są numerem 1

dc = False
bool(dc)
#False

bool([None, 0]) #niepusta lista zwraca wartosc ture. None to inaczej NULL/void
#True

>>> 1/2
0
>>> 1./2.
0.5
>>> 1./3.
0.33333333333333331
>>> 1./3
0.33333333333333331
>>> 1.//3. # // zawsze zwraca wynik calkowity
0.0
>>> 2**3 # 2 do potęgi 3
8
>>> 5%2 # modulo, reszta z dzielenia
1

>>> int(12.34) # funkcje fabryczne, tworzymy now obiekt na podstawie obiektu typu float //w innych jezykach nazyway rzutowaniem
12
>>> float(2)
2.0
>>> abs(-3) #modul z liczby
3
>>> round(3.1415, 2) # zaokraglanie do okreslonej liczby miejsc po przecinku
3.1400000000000001

>>> divmod(15,6) # 15/6 = 2 calosci i reszty 3
(2, 3)
>>> divmod(2,3)
(0, 2)

>>> ord('a')
97
>>> chr(65)
'A'
>>> chr(97)
'a'

#stringi
>>> "%s jest numerem %d" % ('python', 1)
'python jest numerem 1'
>>> """czesc wam"""
'czesc wam'
>>> [123, 'sd', 2.333]
[123, 'sd', 2.3330000000000002]

#lista
>>> words = 'jakis dlugi text'
>>> [x.upper() for x in words]
['J', 'A', 'K', 'I', 'S', ' ', 'D', 'L', 'U', 'G', 'I', ' ', 'T', 'E', 'X', 'T']

#tuple (krotka)
'''
Krotka (ang. tuple) - struktura danych będąca odzwierciedleniem matematycznej n-tki, tj. uporządkowanego ciągu wartości.
Krotki przechowują stałe wartości o różnych typach danych - nie można zmodyfikować żadnego elementu, odczyt natomiast wymaga
podania indeksu liczbowego żądanego elementu.
'''
>>> (1, 2.3)
(1, 2.2999999999999998)
>>> (1,)
(1,)
>>> ('musisz uzyc przecinka nawet gdy jest tylko jeden element',)
('musisz uzyc przecinka nawet gdy jest tylko jeden element',)

''' operacje na string '''
>>> s = 'Python'
>>> s[0]
'P'
>>> s[3]
'h'
>>> s[-1]
'n'
>>> s[1:4] # pobieramy od elementu o indexie 1 do elementu o indexie 4 (ale element o indexie=4 nie jest wycinany)
'yth'
>>> s[2:4]
'th'
>>> s[:4] # pobieramy od początku
'Pyth'
>>> s[3:] # pobieramy do konca
'hon'
>>> s[3:-1] # od 3 do ostatniego znaku (za wyjatkiem ostatniego znaku)
'ho'
>>> s[:]
'Python'
>>> str(s)
'Python'

''' łączenie stringów '''
>>> 'Python' + ' ' + 'Django' + " sa super"
'Python Django sa super'
>>> 'lol'*3
'lollollol'
>>> 'an' in 'Django'
True
>>> 'abc' not in 'Django'
True
>>> 'xyz' in 'Django'
False

>>> '%s%s' % ('foo', 'bar') # powinno sie uzywac operatora % formatowania łancuchów zamiast konkatenacji + poniewaz jest wydajniejszy. W Python 2.6 powinno sie uzywac juz funkcji format() zamiast %
'foobar'
>>> 'X'.join(['aa','bb', 'cc']) # lista łancuchów zostaje połączona znakiem X
'aaXbbXcc'

>>> list1 = ['a', 'b']
>>> list2 = ['c', 'd']
>>> list1+list2 # konkatenacja
['a', 'b', 'c', 'd']
>>> list1.extend(list2) # do pierwszej listy dodajemy na koniec list2
>>> list1
['a', 'b', 'c', 'd', 'c', 'd']

''' str.40 listy '''
>>> book = ['Programowanie', 'webowe', 'Python', 8]
>>> book.append(2008) # dodajemy na koniec element
>>> book.insert(1, 'aplikacje') # w miejsce indexu=1 wstawiamy element a reszte przesuwamy w prawo o 1
>>> book
['Programowanie', 'aplikacje', 'webowe', 'Python', 8, 2008]
>>> book[:3] # wycinamy od poczatku do 3 indexu (bez index=3)
['Programowanie', 'aplikacje', 'webowe']
>>> 'Django' in book #sprawdzamy czy wystepuje w liscie
False
>>> book.remove(8) # usuwamy element o wartosci 8
>>> book.pop(-1) # usuwamy element o indexie = -1 czyli ostatni
2008
>>> book
['Programowanie', 'aplikacje', 'webowe', 'Python']
>>> book*2 # powtarzanie (duplikacja)
['Programowanie', 'aplikacje', 'webowe', 'Python', 'Programowanie', 'aplikacje', 'webowe', 'Python']
>>> book.extend(['width', 'Django']) # dołączamy tablice na koncu
>>> book
['Programowanie', 'aplikacje', 'webowe', 'Python', 'width', 'Django']

''' str 41 '''
>>> book = ['Programowanie', 'aplikacje', 'webowe', 'Python', 8, 2008]
>>> book
['Programowanie', 'aplikacje', 'webowe', 'Python', 8, 2008]
>>> book.sort() # metoda dziala na obiekcie book modyfikujac go
>>> book
[8, 2008, 'Programowanie', 'Python', 'aplikacje', 'webowe']

''' str. 41
np. przy metodzie upper() dla stringow zwracany jest nowy obiekt string a oryginalny nie jest modyfikowany
aby tablice mozna bylo sortowac i byla zwracana kopia tablicy posortowanej nalezy uzyc funkcji sorted() lub reversed()

'''
>>> book
['webowe', 'aplikacje', 'Python', 'Programowanie', 2008, 8]
>>> sorted(book) # sortowanie i zwrocenie kopii obiektu
[8, 2008, 'Programowanie', 'Python', 'aplikacje', 'webowe']
>>> book
['webowe', 'aplikacje', 'Python', 'Programowanie', 2008, 8]

''' str. 41 Rozwinięcia list '''
>>> data = [x+1 for x in range(10)]
>>> data
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

>>> a = [x+2 for x in range(5)] # tworzy liste x=0 na początku, dla indexu=0 x+2=2. Dla indexu=1 x+2=1+2=3 itd.
>>> a
[2, 3, 4, 5, 6]

>>> tab = [x+3 for x in range(3,7)] # tworzymy liste z elementow x+3 przechodzą po petli for w przedziale od (3,7) gdzie ostatnim elementem x jest liczba 7-1=6
>>> tab
[6, 7, 8, 9] # 3+3=6, itd., 6+3=9

>>> even_numbers = [x for x in range(10) if x%2==0] # tu podobnie, ostatni x=9 stąd konczymy na 8 bo 8 dzieli sie przez dwa
>>> even_numbers
[0, 2, 4, 6, 8]

''' str. 42 Wyrazenia generatorowe - oszczędzają pamięc kosztem szybkości. W Python 3.0 rozwinięcia list zostały uznane za
przestarzałe i zaleca się uzywanie generatorow '''
>>> numbers = (x for x in range(1000) if x % 2 == 0)
>>> numbers
<generator object <genexpr> at 0x02CB3490>

''' str. 43 Łańcuchy znaków
metody zwracaja nowy obiekt poniewaz nie mozna modyfikowac łańcuchów
'''
>>> s = 'Django jest super'
>>> words = s.split()
>>> words
['Django', 'jest', 'super']
>>> ' '.join(words)
'Django jest super'
>>> '::'.join(words)
'Django::jest::super'
>>> ''.join(words)
'Djangojestsuper'
>>> s.upper()
'DJANGO JEST SUPER'
>>> s.upper().isupper()
True
>>> s.title() #wszystkie slowa zaczynaja sie od duzej litery
'Django Jest Super'
>>> s.capitalize() # pierwsze slowo od duzej litery
'Django jest super'
>>> s.count('o') # liczba wystąpień znaku 'o'
1
>>> s.find('go') # na ktorym indexie wystepuje/zaczyna sie slowo
4
>>> s.find('xxx') # -1 oznacza ze nie znaleziono slowa xxx
-1
>>> s.startswith('Python') # czy łańcuch zaczyna się od słowa Python
False
>>> s.endswith('super') # czy na koncu łańcucha występuje słowo 'super'
True
>>> s.endswith('per')
True
>>> s.replace('Django', 'Python') # znajdź i zamień
'Python jest super'

>>> txt = 'Jakis bardzon Dlugi textn na kilka linijekn'
>>> txt.splitlines() # dzieli txt na osobne linie, dzielac po znakach nowej linii n
['Jakis bardzo', ' Dlugi text', ' na kilka linijek']
>>> txt.rstrip() # usuwa znak nowej linii z konca łańcucha
'Jakis bardzon Dlugi textn na kilka linijek'

>>> txt = 'nabcde n efg n hijk n';
>>> txt.strip() # usuwa n z początku i konca łańcucha
'abcde n efg n hijk'

''' str.44 Oznaczenia łancuchów
OPIS METOD: str. 45 ============================================================================================================================
'''
>>> mystring = u'To jest unikod!'
>>> mystring
u'To jest unikod!'
>>> print mystring # nie powoduje wyswietlenia oznaczenia u
To jest unikod!
>>> str(mystring) #
'To jest unikod!'

'''
Oznaczenie łanucha jako surowy informuje interpreter zeby nie przetwarzal znakow specjalnych np. n-tki
surowe lancuchy wykorzystuje sie np. w sciezkach do plikow lub w wyrazeniach regularnych
'''
>>> raw_string = r'To jest surowy lancuch (ang. raw)'
>>> raw_string
'To jest surowy lancuch (ang. raw)'
>>> filename = r'C:tempnowyrobots.txt' # Oznaczone jako surowy łańcuch ponieważ w ścieżce występuje n a nie chcemy aby był potraktowany jak znak nowej linii
>>> filename
'C:\temp\nowy\robots.txt'

''' str. 46 Operator formatowania łancuchów i potrójne cudzysłowy
dyrektywy formatujące:
%s - string
%d - liczba
%.1f - //np. liczba 1.2
'''
>>> s = 'Django jest super!'
>>> '%s jest numerem %d' % (s[:6], 1) # operator formatujący łączy łanuch formatujący z krotką po prawej!!
'Django jest numerem 1'
>>> '%s jest numerem %d i takze %d' % (s[:6], 1, 2)
'Django jest numerem 1 i takze 2'

# potrójne cudzysłowy pozwalają na załączanie znaków specjalnych w sposób dosłowny. Zamiast pisać n wciskamy enter by przełamać wiersz
>>> hi = '''hej
... tam'''
>>> hi
'hejntam'
>>> print hi
hej
tam

>>> xml = '''
... <?xml version="1.0"?>
... <Request version="%.1f">
... <Header>
... <APIName>PWDDapp</APIName>
... <APIPassword>youwillneverguess</APIPassword>
... </Header>
... <Data>
... <Payload>%s</Payload>
... <Timestamp>%s</Timestamp>
... </Data>
... </Request>
... '''
>>> import time # wykorzystamy time.ctime() do pobrania znacznika czasu
>>> VERSION = 1.2 # ustawiamy wersję aplikacji
>>> def sendXML(data): # definiujemy funkcje do wysylania danych XML
... 'Wysylamy dane XML'
...
>>> payload = 'scisle tajna informacja'
>>> sendXML(xml % (VERSION, payload, time.ctime()))
>>> print xml % (VERSION, payload, time.ctime()) #wydrukujemy przyklad dzialania operatora formatowania łancuchów na zmiennej xml

<?xml version="1.0"?>
<Request version="1.2">
<Header>
<APIName>PWDDapp</APIName>
<APIPassword>youwillneverguess</APIPassword>
</Header>
<Data>
<Payload>scisle tajna informacja</Payload>
<Timestamp>Thu Jul 22 14:25:20 2010</Timestamp>
</Data>
</Request>



''' str. 47 Krotki - tablice ktore mozna tylko odczytywac. Nie mozna ich modyfikowac '''
x = (1, 2, 'ss')
>>> x.index(2) # na ktorej pozycji jest element 2
1
>>> x.index('ss') # na ktorej pozycji jest element 'ss'
2

>>> a = ('jeden', "dwa") # krotka (tuple)
>>> a[0]
'jeden'
>>> b = ('tylko-jeden') # to nie jest krotka bo nie ma przecinka na końcu
>>> b[0] # zmienna b zostanie potraktowana jako string
't'
>>> c = ('tylko-jeden',) # krotka (tuple)
>>> c[0]
'tylko-jeden'
>>> d = 'tylko-jeden', # krotka (tuple). Można nie podawać nawiasów ale jest to niezalecane ze względu na przejrzystość
>>> d[0]
'tylko-jeden'

>>> a = 'sddf dsf dsf '
>>> a
'sddf dsf dsf '
>>> b = repr(a) # zwraca ewaluowaną postać obiektu w postaci łańcucha znaków
>>> b
"'sddf dsf dsf '"
>>> c = eval(b) # przywrócenie obiektu na podstawie wyewaluowanego łanucha znakówa
>>> c
'sddf dsf dsf '

''' str. 48 Sekwencyjne funkcje wbudowane i fabryczne '''
>>> a = [1,21,4,5,24]
>>> len(a) # liczebność obiektu
5
>>> max(a) # największy obiekt w sekwencji
24
>>> min(a) # najmniejszy obiekt w sekwencji
1
>>> str(a) # postać łancuchowa do drukowania
'[1, 21, 4, 5, 24]'
>>> tuple(a) # zamienia w postać krotki (tuple)
(1, 21, 4, 5, 24)
>>> list(a) # zamienia w postać listy
[1, 21, 4, 5, 24]
>>> sorted(a) # sortuje rosnąco. reversed() sortuje malejąco
[1, 4, 5, 21, 24]
>>> sum(a) # sumuje elementy sekwencji
55
>>> any(a) # sprawdza czy jakikolwiek element sekwencji ma wartosc true
True
>>> all(a) # sprawdza czy wszystkie elementy sekwencji maja wartosc true
True
>>> zip(a) # zwraca listę krotek, z których n-ta krotka zawiera n-te elementy z podanych sekwencji
[(1,), (21,), (4,), (5,), (24,)]

''' str. 49 Słowniki '''
>>> book = { 'title': 'Python i Django. Programowanie aplikacji webowych', 'year': 2009 }
>>> book
{'year': 2009, 'title': 'Python i Django. Programowanie aplikacji webowych'}
>>> 'year' in book # czy występuje klucz o takiej nazwie w słowniku
True
>>> 'pub' in book
False

# pobierz wartosc klucza pub jesli go nie ma to zwroc argument drugi czyli N/A
''' W przypadku gdy nie podano drugiego argumentu metody get to zwracane jest None '''
>>> book.get('pub', 'N/A')
'N/A'
>>> book['pub'] = 'Wydawnictwo Helion'
>>> book.get('pub', 'N/A') # teraz zwraca wartosc klucza bo on istnieje
'Wydawnictwo Helion'
>>> for key in book:
... print key, ':', book[key] # przecinek dziala tu jak konkatenacja
...
year : 2009
pub : Wydawnictwo Helion
title : Python i Django. Programowanie aplikacji webowych

>>> d = { 'title': 'Python i Django. Programowanie aplikacji webowych', 'year': 2009 }
# setdefault działa jak get ale w przypadku gdy klucz 'pub' nie istnieje to go tworzy i przypisuje mu wartosc
# drugiego argumentu czyli 'Wydawnictwo Helion'
>>> d.setdefault('pub', 'Wydawnictwo Helion')
'Wydawnictwo Helion'
>>> d
{'year': 2009, 'pub': 'Wydawnictwo Helion', 'title': 'Python i Django. Programowanie aplikacji webowych'}
>>> print d.get('a') ''' W przypadku gdy nie podano drugiego argumentu to zwracane jest None '''
None

>>> del d['pub'] # usuwamy pare klucz-wartosc
>>> d
{'year': 2009, 'title': 'Python i Django. Programowanie aplikacji webowych'}
>>> d['title'] = 'Inna nazwa ksiazki' # modyfikujemy wartosc klucza 'title'
>>> d
{'year': 2009, 'title': 'Inna nazwa ksiazki'}
>>> len(d) # zwraca liczbe elementow w słowniku
2

''' Metody słowników str. 51 '''
>>> d.keys() # zwraca klucze słownika
['year', 'title']
>>> d.values() # zwraca wartosci słownika
[2009, 'Inna nazwa ksiazki']
>>> d.items() # zwraca listę której elementami są krotki klucz-wartosc
[('year', 2009), ('title', 'Inna nazwa ksiazki')]

>>> d.iteritems()
<dictionary-itemiterator object at 0x02CCDBD0>

>>> d.pop('year') # usun pare klucz-wartosc dla klucza 'year'
2009
>>> d
{'title': 'Inna nazwa ksiazki'}
>>> e = {'a':'art', 'b':2010}
>>> d.update(e) # polacz slownik d ze slownikiem e
>>> d
{'a': 'art', 'b': 2010, 'title': 'Inna nazwa ksiazki'}

>>> b = {'q':'qwerty', 'w':111}
>>> z = {} # pusty słownik
>>> z.fromkeys(b) # wypelnij slownik z kluczami ze slownika b
{'q': None, 'w': None}

>>> d = {'year': 2009, 'title': 'Inna nazwa ksiazki'}
>>> d.popitem() # usuwa ostatni element słownika i zwraca go w postaci klucz-wartosc
('title', 'Inna nazwa ksiazki')
>>> d
{'year': 2009}
>>> d.popitem()
('year', 2009)
>>> d
{}

>>> d = {'year': 2009, 'title': 'Inna nazwa ksiazki'}
>>> d
{'title': 'Inna nazwa ksiazki', 'year': 2009}
>>> d.clear() # usuwa wszystkie pary klucz-wartosc
>>> d
{}

# zagłebiona struktura słownika
>>> d = {'a':'aaaa','b':{'q':'qqq','w':222}}
>>> d
{'a': 'aaaa', 'b': {'q': 'qqq', 'w': 222}}
>>> d['b']
{'q': 'qqq', 'w': 222}
>>> d['b']['q']
'qqq'

''' str. 52 Instrukcje warunkowe. Konstrukcja else-if w pythonie to elif '''
>>> data = raw_input("Wprowadz 't' lub 'n': ") # monit z prosba o podanie znaku
>>> if data[0] == 't':
... print "Wpisales 't'."
... elif data[0] == 'n':
... print "Wpisales 'n'."
... else:
... print 'Wprowadzono niepoprawny klucz!'
...
Wpisales 't'.

''' str. 52 Pętle '''
>>> i = 0
>>> while i<5:
... print i
... i+=1
...
0
1
2
3
4

>>> for line in open('C:tmpsome_file.txt'):
... if 'error' in line:
... print line

''' str. 53 Wykorzystanie funkcji enumerate() w modelach Djangojestsuper
Dobry przyklad - zobacz ksiazka str 53.

STATUS_CHOICES = enumerate(("stale", "zgniecione", "plynne"))

class IceCream(models.Model):
flavor = models.CharField(max_lenght=50)
status = models.IntegerFiled(choices=STATUS_CHOICES)

W bazie danych status twoich lodow bedzie przechowywany jako liczba całkowita 0, 1, 2
jednak w panelu administracyjnym Django będą wyświetlane opisy tekstowe.

'''
>>> data = (123, 'abc', 3.14) # krotka
>>> for i, value in enumerate(data): # funkcja enumerate() pozwala iterować po elementach i zliczać je
... print i, value
...
0 123
1 abc
2 3.14

''' str. 54 Obsługa wyjątków '''
>>> try:
... f = open(filename, 'r')
... except IOError, e:
... return False, str(e)

>>> try:
... process_some_data()
... except (TypeError, ValueError), e:
... print "Blad: wprowadziles niepoprawne dane", e
...

# moj wlasny przyklad
>>> try:
... a = 1/0
... except Exception, e: # łapie każdy wyjątek. Jeśli wcześniej podano jakies except i zadne z nich nie złapało wyjątku to except Exception go złapie ostatecznie!
... print str(e)
...
integer division or modulo by zero

''' str.54 Ostatni blok except wykorzystuje fakt że typ Exception jest klasą bazową dla (niemal) wszystkich klas wyjątków
Jeśli więc utworzony wyjątek nie zostanie złapany przez wcześniejsze klauzule except, zostanie on obsłużony przez ostatni blok '''
>>> try:
... process_some_data()
... except (TypeError, ValueError), e:
... print "Blad: wprowadziles niepoprawne dane", e
... except ArithmeticError, e:
... print "Blad: wystapil blad w obliczeniach", e
... except Exception, e:
... print "Blad: wprowadziles niepoprawne dane", e
...
Blad: wprowadziles niepoprawne dane name 'process_some_data' is not defined

''' str. 55 Klauzula finally
Jeśli nie dochodzi do wywołania wyjątku, kod w klauzuli finally jest wykonywany tuż po zakończeniu sekcji try. Jeśli błąd nastąpi
kod z sekcji finally również zostanie wykonany. Nie dojdzie jednak do obsłużenia wyjątku, przez co zostanie on wysłany wzdłuż
łańcucha funkcji (do kolejnych funkcji nadrzędnych) w poszukiwaniu kodu obsługi.
'''
>>> try:
... get_mutex()
... do_some_stuff()
... finally:
... free_mutex()

>>> try:
... get_mutex()
... do_some_stuff()
... except (IndexError, KeyError, AttributeError), e:
... log("Blad: Proba pobrania nieistniejacego elementu")
... finally:
... free_mutex()

''' str. 55 Rzucanie wyjątkami z wykorzystaniem raise

Wbudowane wyjątki
http://docs.python.org.pl/lib/module-exceptions.html

str, 56 Popularne wyjątki w Python

'''
>>> def foo(must_be_positive_int):
... '''foo() - pobiera i przetwarza liczbę'''
... if not isinstance(must_be_positive_int, int):
... raise TypeError("ERROR foo(): do funkcji nalezy przekazac liczbe!")
... if must_be_positive_int < 1:
... raise ValueError("ERROR foo(): liczba musi byc wieksza od zera!")

''' str. 57 Pliki '''
>>> f = open('test.txt', 'w') # otworz plik do zapisu
>>> f.write('foon')
>>> f.write('barn')
>>> f.close()
>>> f = open('test.txt', 'r') # otworz plik do odczytu
>>> for line in f:
... print line.rstrip() # usun znaki nowej linii
...
foo
bar
>>> f.close()
>>> f = open('test.txt', 'r')
>>> for l in f:
... print l # brak rstrip() powoduje podwojne wyswietlenie w konsoli znaku nowej linii. Jeden n pochodzi z pliku a drugi znak n wstawia instrukcja print
...
foo

bar

''' str. 58 Deklarowanie i wywoływanie funkcji '''
>>> def foo(x):
... print x
...
>>> foo(123)
123

>>> import httplib
>>> def check_web_server(host, port, path):
... h = httplib.HTTPConnection(host, port)
... h.request('GET', path)
... resp = h.getresponse()
... print 'Odpowiedz HTTP:'
... print ' status =', resp.status
... print ' powod =', resp.reason
... print 'Naglowki HTTP:'
... for hdr in resp.getheaders():
... print ' %s: %s' % hdr
...
>>> check_web_server('www.python.org', 80, '/')
Odpowiedz HTTP:
status = 200
powod = OK
Naglowki HTTP:
content-length: 18271
accept-ranges: bytes
server: Apache/2.2.9 (Debian) DAV/2 SVN/1.5.1 mod_ssl/2.2.9 OpenSSL/0.9.8g mod_wsgi/2.5 Python/2.5.2
last-modified: Fri, 23 Jul 2010 10:34:04 GMT
etag: "105800d-475f-48c0b92e73f00"
date: Fri, 23 Jul 2010 21:06:43 GMT
content-type: text/html


''' str. 58 Parametry słów kluczowych (w wywołaniach funkcji) '''
>>> check_web_server(port=80, path='/', host='www.python.org')

>>> foo(x=22)
22

''' str. 59 Argumenty domyślne (w sygnaturach funkcji)
Muszą być umieszczane po argumentach wymaganych
'''
>>> def check_web_server(host, port=80, path='/'):
... h = httplib.HTTPConnection(host, port)
... h.request('GET', path)
... resp = h.getresponse()
... print 'Odpowiedz HTTP:'
... print ' status =', resp.status
... print ' powod =', resp.reason
... print 'Naglowki HTTP:'
... for hdr in resp.getheaders():
... print ' %s: %s' % hdr
...

# WAZNE @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
''' str. 59 Listy i słowniki jako argumenty domyślne
Listy i słowniki są modyfikowalne podczas gdy łańcuchy znaków i liczby nie. Z tego względu używanie list i słowników
jako argumentów domyślnych jest niebezpieczne, ponieważ jeden i ten sam egzemplarz listy istnieje w trakcie wielu
wywołań funkcji.
===============================================================================================================================================
'''
>>> def func(arg=[]):
... arg.append(1)
... print arg
...
>>> func()
[1]
>>> func()
[1, 1]
>>> func()
[1, 1, 1]

''' Listy i słowniki są modyfikowalne. Co może powodować błędy jeśli o tym zapomnimy '''
>>> aa = [1,2]
>>> cc = aa
>>> cc
[1, 2]
>>> cc.extend([0,0]) # dołączamy liste [0,0] do cc
>>> cc
[1, 2, 0, 0]
>>> aa # aa zostało zmodyfikowane również mimo że metode extend wywołaliśmy na cc
[1, 2, 0, 0]

''' str. 60 Funkcje są obiektami pierwszej klasy.
Referencje
'''
>>> foo = 42
>>> def bar():
... print "bar"
...
>>> bar()
bar
>>> baz = bar # tworzymy alias (referencje) do obiektu funkcji bar. Nie ma koniecznosci uzycia nawiasow w nazwie bar
>>> bar() # wywołanie funkcji bar()
bar
>>> baz() # wywolanie funkcji bar() przez alias baz()
bar

''' wywołanie funkcji przez alias baz() i przez bar()
Ciekawy przyklad.

Gdy chcesz przekazać funkcję jak zwykłą zmienna, korzystasz jedynie z jej nazwy (tak jak w powyższej pętli for)
To zachowanie podkreśla różnicę między odwoływaniem się do funkcji za pomocą nazwy - na przykład bar - i wywołaniem jej -
na przykład bar()

'''
>>> function_list = [bar, baz] # tworzymy liste skladajaca sie z obiektow bar, baz (baz jest referencja do obiektu bar)
>>> for function in function_list: # iterujemy po liście wywołujac nazwy z niej jako wywołanie funkcji uzywajac ()
... function() # function jest tu zastepowane kolejno przez bar, baz wiec są to tak na prawdę wywołania funkcji bar(), baz() przy czym baz jest referencją do bar jak było wspomniane wcześniej
...
bar
bar

''' str.61,62 Funkcje anonimowe
Wyrażenia vs instrukcje
Wyrażenie zwraca wartoc, która zawsze jest obiektem Pythona.
Fragmenty kodu które nie powodują powstania obiektów nazywane są instrukcjami. Do instrukcji zalicza się polecenia if, print, for, while,
wykonują one konkretne czynności ale nie zwracają ani nie generują żadnej wartości.

Wykorzystanie wyrażeń lambda (funkcje anonimowe)
'''
#1. przykład użycia lambda
# do zmiennej key przypisywana jest wartosc zwracana przez funkcję anonimową lambda która przyjmuje argument przypisywany do zmiennej person
# funkcja anonimowa zwraca person.last_name i ta wartość jest właśnie przypisywana do key
>>> sorted(list_of_people, key=lambda person: person.last_name)


#2. gdy zamierzamy wielokrotnie uzywac funkcji to juz nie czynnimy jej anonimową (lambda)
>>> def get_last_name(person):
... return person.last_name
...
>>> sorted(list_of_people, key=get_last_name)

#3. lambda jest dokładnym odpowiednikiem funkcji - ale dalej podkreśla pierwszoklasową naturę funkcji Pythona
# przyklad nieszczegolnie przydatny w praktyce. Zamiast niego powinno sie uzywac tak jak w pierwszym przykladzie.
>>> get_last_name = lambda person: person.last_name
>>> sorted(list_of_people, key=get_last_name)

# sortowanie odwrotne
>>> list_of_people = [2, 324, 12, 1]
# użycie argumentu opcjonalnego ktory w definicji funkcji ma wartosc False. Dzieki zapisowi reverse=True
# mozna bylo pominac kolejnosc opcjonalnych argumentow. Mianowicie argument reverse jest na 4 pozycji w deklaracji funkcji sorted
>>> sorted(list_of_people, reverse=True)
[324, 12, 2, 1]

# lambda is just an in-line function
# przyklady z Manual'a
>>> g = lambda x: x*2
>>> g(3)
6

>>> (lambda x: x*2) (5) # wywołamy funkcję lambda na elemencie 5
10

''' str. 63 *args i **kwargs
korzystamy z wcześniejszej definicji check_web_server()

Gdy widzimy * możemy się spodziewać krotki lub listy
Gdy widzimy ** możemy się spodziewać słownika

'''
>>> host_info = ('www.python.org', 80, '/') # krotka
>>> check_web_server(host_info[0], host_info[1], host_info[2])
Odpowiedz HTTP:
status = 200
powod = OK
Naglowki HTTP:
content-length: 18271
accept-ranges: bytes
server: Apache/2.2.9 (Debian) DAV/2 SVN/1.5.1 mod_ssl/2.2.9 OpenSSL/0.9.8g mod_wsgi/2.5 Python/2.5.2
last-modified: Fri, 23 Jul 2010 10:34:04 GMT
etag: "105800d-475f-48c0b92e73f00"
date: Sat, 24 Jul 2010 10:44:53 GMT
content-type: text/html


# wyrażenie *host_info rozpakowuje naszą krotkę i działa to tak jak wyżej check_web_server(host_info[0], host_info[1], host_info[2])
>>> check_web_server(*host_info)
Odpowiedz HTTP:
status = 200
powod = OK
Naglowki HTTP:
content-length: 18271
accept-ranges: bytes
server: Apache/2.2.9 (Debian) DAV/2 SVN/1.5.1 mod_ssl/2.2.9 OpenSSL/0.9.8g mod_wsgi/2.5 Python/2.5.2
last-modified: Fri, 23 Jul 2010 10:34:04 GMT
etag: "105800d-475f-48c0b92e73f00"
date: Sat, 24 Jul 2010 10:46:55 GMT
content-type: text/html



>>> d_host_info = { 'host': 'www.python.org', 'port': 80, 'path': '/' }
>>> check_web_server(**d_host_info) # **d_host_info rozpakowanie słownika
Odpowiedz HTTP:
status = 200
powod = OK
Naglowki HTTP:
content-length: 18271
accept-ranges: bytes
server: Apache/2.2.9 (Debian) DAV/2 SVN/1.5.1 mod_ssl/2.2.9 OpenSSL/0.9.8g mod_wsgi/2.5 Python/2.5.2
last-modified: Fri, 23 Jul 2010 10:34:04 GMT
etag: "105800d-475f-48c0b92e73f00"
date: Sat, 24 Jul 2010 10:53:25 GMT
content-type: text/html






''' str 64. Zmienne argumenty
(kolejnosc argumentow w definicji funkcji [argumentach wymaganaych, argumentach domyslnych, argumenty zmienne])
'''
>>> def daily_sales_total(*all_sales):
... total = 0.0
... for each_sale in all_sales:
... total += float(each_sale)
... return total
...
>>> daily_sales_total()
0.0
>>> daily_sales_total(10.00)
10.0
>>> daily_sales_total(5.00, 1.50, '128.75') # możemy przekazywać wiele argumentów w postaci krotki przyjmujacej rozne typy np. liczby, stringi
135.25

''' str. 65 '''
def check_web_server(host, port, path, *args, **kwargs): # przyklad definicji funkcji z zmiennymi argumentami *args i **kwargs

def f(*args, **kwargs): # "uniwersalna" sygnatura metody Pythona która składa się wyłącznie ze zmiennych argumentów

''' str 66 Dekoratory '''

# ogolny wzor
>>> @deco
... def foo():
... pass

''' rejestrowanie wywołan funkcji w momencie jej wywołania '''
>>> def log(func):
... def wrappedFunc():
... print "*** Wywołano %s()" % func.__name__
... return func()
... return wrappedFunc
...
>>> @log
... def foo():
... print "wewnątrz foo()"
...
>>> foo()
*** Wywołano foo()
wewnątrz foo()

''' str. 67 '''
>>> @decomaker(deco_args)
... def foo():
... pass
# powyższy zapis odpowiada poniżemu wywołaniu
foo = decomaker(deco_args)(foo)
''' w tym przypadku decomaker pobiera argumenty deco_args i zwraca dekorator, który opakowuje funkcje foo '''

''' Przyklad prezentuje wykorzystanie wielu dekoratorow '''
>>> @deco1(args)
... @deco2
... def foo():
... pass
# powyższy przykład odpowiada poniższej konstrukcji
foo = deco1(deco_args)(deco2(foo))

''' przyklady ze strony: http://personalpages.tds.net/~kent37/kk/00001.html '''
>>> def show_func(f):
... print f.__name__
...
>>> def foo():
... print 'foo here'
...
>>> show_func(foo)
foo

>>> def make_adder(x):
... def adder(y):
... return x+y
... return adder
...
>>> a = make_adder(5)
>>> a(10)
15
>>> a(4)
9
>>> make_adder(5)(4) # wywołujemy funkcje make_adder z argumentem 5, i spod niej funkcje z arg 4 co zwraca nam 9
9
>>> make_adder(3)(2)
5

''' Wrapping a function - funkcje zawijalne
W przykladzie wazna jest wczesniej zdefiniowana funkcja foo() ktora zwraca napis foo here

Do zmiennej bar przypisujemy show_call(foo) co powoduje ze w funkcji shown tworzy sie napis
'Calling foo' bo jako argument show_call przekazalismy nazwe funkcji foo
Teraz mozemy uzywac bar jako wywolanie funkcji shown ktora rownoczesnie zawsze wywoluje foo()
'''
>>> def show_call(f):
... def shown(*args, **kwds):
... print 'Calling', f.__name__
... return f(*args, **kwds)
... return shown
...
>>> bar = show_call(foo)
>>> bar()
Calling foo
foo here

''' Jeśli owinietą funkcje foo przypiszemy do nazwy foo bedziemy mogli uzywac foo jako owinietej funkcji '''
>>> foo = show_call(foo)
>>> foo()
Calling foo
foo here





''' str 68 Programowanie obiektowe '''
>>> class AddressBookEntry(object): # Podstawowa klasa Pythona 'object' - zawsze po niej dziedziczymy
... version = 0.1 # Zmienna statyczna. Działa w obrębie wielu egzemplarzy klasy. Musi mieć przypisaną wartosc aby była statyczna
... def __init__(self, name, phone): # Inicjalizator zamiast konstruktora. Wymagane self (ponieważ w Python zalecane jest jawne podawanie argumentów)
... self.name = name
... self.phone = phone
... def update_phone(self, phone): # Wymagane self
... self.phone = phone


>>> jan = AddressBookEntry('Jan Kowalski', '123 456 789') # Tworzenie egzemplarza
>>> maria = AddressBookEntry('Maria Kowalska', '234 354 463')
>>> jan.phone # Odwołanie do zmiennej
'123 456 789'
>>> jan.update_phone('111 222 333') # Wywołanie metody
>>> jan.phone
'111 222 333'

''' str. 69, 77 Tworzenie dynamicznych atrybutów instancji '''
>>> jan.tatto = 'Mama'
>>> jan.tatto
'Mama'

''' str.69 Klasy pochodne '''
>>> class EmployeeAddressBookEntry(AddressBookEntry):
... def __init__(self, name, phone, id, social):
... AddressBookEntry.__init__(self, name, phone) # Wywołujemy metodę która za nas przypisze name, phone. Wymagane jest słowo self, poniewaz nie odnosimy sie do egzemplarza tylko do klasy
... self.empid = id
... self.ssn = social

''' str.70 Klasy wewnętrzne
Są zdefinowane wewnątrz innych klas i są widoczne tylko wewnątrz klas których zostały zdefiniowane.
'''
class MyClass(object):

class InnerClass:
pass



''' str.71 Moduł re
'''
>>> import re
>>> m = re.search(r'test', 'atest') # serach - wyszukiwanie wzorca
>>> print m
<_sre.SRE_Match object at 0x032F0058> # obiekt
>>> m.group() # Obiekt m ma dostępne metody np. group
'test'
>>> m = re.search(r'brak', 'atest') # r - surowe znaki np. n nie jest interpertowane jako znak nowej linii
>>> print m
None # Nie znaleziono slowa brak w slowie atest

''' str. 72 Wyrażenia regularne.
Dopasowanie wzorca
'''
>>> import re
>>> m = re.match(r'test', 'atest') # Dopasowanie wzorca
>>> if m is not None:
... print m.group()
...
>>> print m
None
>>> m = re.search(r'test', 'atest') # Wyszukiwanie wzorca
>>> if m is not None:
... print m.group()
...
test

''' str.72 Moduły '''
>>> import random # Importujemy cały moduł
>>> print random.choice(range(10))
9
''' cały moduł jest ładowany. zapisywane jest do pamieci tylko odwolanie do okreslonej funkcji choice '''
>>> from random import choice # Importujemy wybraną funkcję (bez nazwy modułu). Moduł jako taki jest ładowany do pamięci w całości więc ten przyklad nie zwieksza wydajnosci
>>> print choice(range(10))
3

# WAZNE
''' str.74 Zmienność (modyfikowalność)
Proste lub "skalarne" typy, włączając w to liczby całkowite i inne typy liczbowe są niezmienne, podobnie jak
typy łańcuchowe (np. str, unicode) i krotki. Niemal wszystkie inne obiekty - listy, słowniki, klasy, obiekty klas itd. są modyfikowalne.

Obiekty niezmienne są przekazywane przez wartość, zaś zmienne przez referencję.
'''

''' str.75 Kopiowanie obiektów a zmienność '''
>>> mylist = [1, 'a', ['foo', 'bar']]
>>> mylist2 = list(mylist) # Tworzymy płytką kopie listy 'mylist'
>>> mylist2[0] = 2
>>> mylist[2][0] = 'biz' # Modyfikujemy podlistę w liscie pierwszej co powoduje ze jednoczesnie jest ona zmieniana w liscie 'mylist2'
# Jest to spowodowane tym ze kopiowane są referencje do obiektów ktore są modyfikowalne
>>> print mylist
[1, 'a', ['biz', 'bar']]
>>> print mylist2
[2, 'a', ['biz', 'bar']]
'''
Aby wykonać głęboką kopię (deepcopy) należy skorzystać z modułu 'copy' i metody copy.deepcopy
Ten rodzaj kopiowania wykorzystuje rekursję (co powoduje problemy, jesli wystepują wzajemne cykliczne referencje)
Z tego względu nie wszystkie obiekty mogą być kopiowane w pełni.

shallow copy - kopiowanie płytkie (kopiowane są referencje do zmiennych obiektów)
deep copy - kopiowanie pełne, głębokie (kopiowane są wartości zmiennych obiektów a nie tylko referencje do nich)
'''

# Moje przyklady
>>> mylist = [1, 'a', ['foo', 'bar']]
>>> mylist2 = list(mylist)
>>> mylist2[0] = 2
>>> mylist[2][0] = 'biz'
>>> mylist2[1] = 4
>>> print mylist
[1, 'a', ['biz', 'bar']]
>>> print mylist2
[2, 4, ['biz', 'bar']]
>>> mylist2[1] = 'cc'
>>> print mylist
[1, 'a', ['biz', 'bar']]
>>> print mylist2
[2, 'cc', ['biz', 'bar']]
>>> mylist[1] = 'bb'
>>> print mylist
[1, 'bb', ['biz', 'bar']]
>>> print mylist2
[2, 'cc', ['biz', 'bar']]

''' str.76 Konstruktor vs Inicjalizator

Aby jawnie usunąć obiekt z pamieci korzystamy z instrukcji:
>>> del objekt

>>> t = ['a', 2]
>>> t
['a', 2]
>>> a = t
>>> a
['a', 2]
>>> del a
>>> a # Usunięta tylko referencja a na t
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
NameError: name 'a' is not defined
>>> t # Nadal możemy odwołac się do t
['a', 2]

'''
>>> from time import ctime
>>> class MyClass(object):
... def __init__(self, date):
... print "Utworzono instację w dniu: ", date
...
>>> m = MyClass(ctime())
Utworzono instację w dniu: Mon Sep 06 21:08:45 2010

''' str.78 Tworzymy łańcuchy dokumentacji
Tworze katalog 'mydir' w c:python26
W tym katalogu umieszczam plik foo.py oraz plik __init__.py który pozwala traktować moduł jako pakiet. (Plik __init__ jest pusty)
Importujemy foo z katalofu mydir
'''
>>> from mydir import foo
>>> foo.__doc__
'foo.py -- przykladowy modul prezentujacy lancuchy dokumentacji'
>>> foo.Foo.__doc__
'Foo() - klasa pusta - do zaimplementowania'
>>> foo.bar.__doc__
"bar(x) - lanuch dla funkcji bar, wypisuje swoj argument: 'x'"
>>>
>>> help(foo)
Help on module mydir.foo in mydir:

NAME
mydir.foo - foo.py -- przykladowy modul prezentujacy lancuchy dokumentacji

FILE
c:python26mydirfoo.py

CLASSES
__builtin__.object
Foo

class Foo(__builtin__.object)
| Foo() - klasa pusta - do zaimplementowania
|
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)

FUNCTIONS
bar(x)
bar(x) - lanuch dla funkcji bar, wypisuje swoj argument: 'x'