Python wyposażony jest w zestaw wielu instrukcji, nie tylko w while, którą już poznaliśmy. Są one dobrze znane z innych języków programowania, choć posiadają swój lokalny koloryt.
Zdaje mi się, że najbardziej znaną instrukcją jest instrukcja if. Np.:
>>> x = int(raw_input("Proszę podać liczbę: "))
>>> if x < 0:
... x = 0
... print 'Ujemna zmieniła się na zero'
... elif x == 0:
... print 'Zero'
... elif x == 1:
... print 'Jeden'
... else:
... print 'Więcej'
...
Można wstawić zero lub więcej części elif, a część else jest opcjonalna. Słowo kluczowe elif jest skrótem instrukcji 'else if' i przydaje się, gdy chce się uniknąć kolejnej indentacji. Sekwencja if ... elif ... elif ... zastępuje instrukcje switch lub case spotykane w innych językach.4.1
Instrukcja for różni się troszeczkę w Pythonie od tego, co używasz w C lub Pascalu. Nie prowadzi się iteracji od liczby do liczby (jak w Pascalu) lub daje się użytkownikowi możliwość definiowania kroku iteracji i warunki zakończenia iteracji (jak w C). Instrukcja for w Pythonie powoduje iterację po elementach jakiejkolwiek sekwencji (np. listy lub łańcucha znaków), w takim porządku, w jakim są one umieszczone w danej sekwencji. Na przykład:
>>> # Mierzy pewne napisy: ... a = ['kot', 'okno', 'wypróżnić'] >>> for x in a: ... print x, len(x) ... kot 3 okno 4 wypróżnić 9
Nie jest bezpiecznym modyfikacja sekwencji, która właśnie jest przedmiotem iteracji (można to zrobić tylko dla mutowalnego typu sekwencji, tzn. listy). Jeśli chce się ją modyfikować, np. duplikować wybrane jej elementy, to przeprowadź iterację na jej kopii. Notacja wykrawania jest tu szczególnie użyteczna:
>>> for x in a[:]: # wykrój całą listę (zrób jej kopię) ... if len(x) > 6: a.insert(0, x) ... >>> a ['wypróżnić', 'kot', 'okno', 'wypróżnić']
Jeśli zaszła potrzeba iteracji określonej zakresem liczbowym (czyli iteracji na sekwencji liczb w Pythonie), można użyć wbudowanej w interpreter funkcji range(). Wynikiem jej działania jest lista zawierająca ciąg arytmetyczny, tzn.:
>>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Podany na jej wejściu punkt końcowy nigdy nie zostanie zawarty w wynikowej
liście. range(10) tworzy listę 10 wartości, a tak naprawdę dokładnie
zbiór dopuszczalnych wartości indeksów dla listy o długości 10. Jeśli jest taka
potrzeba, można określić liczbę początkową tego ciągu albo krok (nawet liczbę
ujemną):
>>> range(5, 10) [5, 6, 7, 8, 9] >>> range(0, 10, 3) [0, 3, 6, 9] >>> range(-10, -100, -30) [-10, -40, -70]
Aby przeglądnąć wszystkie elementy listy łączy się funkcje range() i len(), tak jak poniżej:
>>> a = ['Marysia', 'miała', 'małego', 'baranka'] >>> for i in range(len(a)): ... print i, a[i] ... 0 Marysia 1 miała 2 małego 3 baranka
Instrukcja break, podobnie jak w C, powoduje wyjście z najbliżej zagnieżdżonej pętli for lub while.
Instrukcja continue została również zapożyczona z C, powoduje przejście do następnego kroku iteracji w pętli.
Instrukcje pętli posiadają klauzulę else: jest ona wykonywana w momencie
zakończenia działania pętli przy wyczerpaniu się (dojścia za ostatni element)
listy (pętla for) lub gdy warunek pętli zwraca wartość fałszu
(pętla while), ale nie w momencie opuszczenia pętli w wyniku
zadziałania instrukcji break. Pokazane to zostało na przykładzie
algorytmu poszukiwania liczby pierwszej:
>>> for n in range(2, 10): ... for x in range(2, n): ... if n % x == 0: ... print n, 'równe', x, '*', n/x ... break ... else: ... print n, 'jest liczbą pierwszą' ... 2 jest liczbą pierwszą 3 jest liczbą pierwszą 4 równe 2 * 2 5 jest liczbą pierwszą 6 równe 2 * 3 7 jest liczbą pierwszą 8 równe 2 * 4 9 równe 3 * 3
Instrukcja pass nic nie robi. Może być użyta wszędzie tam, gdzie wymagana jest jakaś instrukcja z powodów składniowych, ale program nie przewiduje w tym miejscu żadnego działania. Na przykład:
>>> while 1: ... pass # Zajęty-poczekaj na naciśnięcie klawisza ...
Możemy stworzyć funkcję, która wypisuje ciąg Fibonaciego o wybranych granicach:
>>> def fib(n): # wypisz ciąg Fibonacciego aż do n ... "Wypisuje ciąg Fibonacciego aż do n" ... a, b = 0, 1 ... while b < n: ... print b, ... a, b = b, a+b ... >>> # Teraz, wywołajmy funkcję, którą przed chwilą zdefiniowaliśmy: ... fib(2000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
Słowo kluczowe def wprowadza definicję funkcji. Musi po nim następować nazwa funkcji i lista jej parametrów formalnych umieszczonych w nawiasach okrągłych. Instrukcje, które tworzą ciało funkcji, są oczywiście wsunięte w stosunku do wiersza zawierającego nazwę funkcji i muszą zaczynać się w nowym wierszu. Opcjonalnie, pierwszy wiersz ciała funkcji może być gołym napisem (literałem): jest to tzw. napis dokumentujący lub (inna nazwa tego zjawiska) docstring.
Istnieją pewne narzędzia, które używają napisów dokumentacyjnych (docstringów) do automatycznego tworzenia drukowanej dokumentacji albo pozwalają użytkownikowi na interaktywne przeglądanie kodu. Dobrym zwyczajem jest pisane napisów dokumentacyjnych w czasie pisania programu: spróbuj się do tego przyzwyczaić.
Wykonanie funkcji powoduje stworzenie nowej tablicy symboli lokalnych używanych w tej funkcji. Mówiąc precyzyjniej: wszystkie przypisania do zmiennych lokalnych funkcji powodują umieszczenie tych wartości w lokalnej tablicy symboli, z czego wynika, że odniesienia do zmiennych najpierw szukają swych wartości w lokalnej tablicy symboli, a potem w globalnej, a dopiero na końcu w tablicy nazw wbudowanych w interpreter. Tak więc, zmiennym globalnym nie można wprost przypisać wartości w ciele funkcji (chyba, że zostaną wymienione w niej za pomocą instrukcji global), aczkolwiek mogą w niej być używane (czytane).
Parametry wywołania funkcyjnego (argumenty) wprowadzane są do lokalnej tablicy symboli w momencie wywołania funkcji. Tak więc, argumenty przekazywane są jej przez wartość (gdzie wartość jest zawsze odniesieniem do obiektu, a nie samym obiektem).4.2Nowa tablica symboli tworzona jest również w przypadku, gdy funkcja wywołuje inną funkcję.
Definicja funkcji wprowadza do aktualnej tablicy symboli nazwę tej funkcji. Nazwa ta identyfikuje wartość, której typ rozpoznawany jest przez interpreter jako funkcja zdefiniowana przez użytkownika. Wartość ta (a właściwie obiekt ) może być przypisana innej nazwie, która potem może zostać użyta jak funkcja. Ta właściwość może posłużyć jako ogólny mechanizm zmiany nazw:
>>> fib <function object at 10042ed0> >>> f = fib >>> f(100) 1 1 2 3 5 8 13 21 34 55 89
Możnaby tutaj naprostować moje opowieści, że fib nie jest funkcją, ale
procedurą. W Pythonie, podobnie jak w C, procedury są specyficznymi funkcjami,
które nie zwracają wartości4.3 Tak naprawdę, mówiąc językiem technicznym,
procedury naprawdę zwracają wartość, aczkolwiek raczej nudną.4.4 Wartość ta nazywana jest None (jest to
nazwa wbudowana). Napisanie wartości None jest w normalnych warunkach
pomijane przez interpreter, jeżeli jest to jedyna wartość, która miała być
wypisana. Można ją zobaczyć, jeżeli naprawdę tego się chce:
>>> print fib(0) None
Bardzo proste jest napisanie funkcji, która zwraca listę liczb ciągu Fibonacciego, zamiast wypisywać je:
>>> def fib2(n): # zwraca wartości ciągu Fibonacciego aż do n ... "Zwraca wartości ciągu Fibonacciego, aż do n" ... wynik = [] ... a, b = 0, 1 ... while b < n: ... wynik.append(b) # zobacz poniżej ... a, b = b, a+b ... return wynik ... >>> f100 = fib2(100) # wywołaj ją >>> f100 # wypisz wynik [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
None.
wynik.append(b) wywołuje metodę obiektu listy
wynik. Metoda jest funkcją ,,należącą'' do obiektu i nazywa się
obiekt.nazwametody, gdzie obiekt jest jakimś tam obiektem (równie
dobrze może to być wyrażenie), a nazwametody jest nazwą metody
zdefiniowanej przez typ obiektu obiekt. Różne typy definiują różne
metody. Metody różnych typów mogą mieć te same nazwy bez powodowania
niejednoznaczności. (Możliwe jest zdefiniowane swoich własnych typów i metod
przy użyciu klas, tak jak pokazane to będzie później).
Metoda append() użyta w przykładzie, zdefiniowana jest dla listy
obiektów: dodaje nowe elementy do końca listy. W tym przykładzie jest to
odpowiednik "wynik = wynik + [b]", ale jest bardziej wydajne.
Możliwe jest definiowanie funkcji ze zmienną liczbą argumentów. Istnieją trzy formy takiej definicji, które mogą być ze sobą splatane.
Najbardziej użyteczną formą jest określenie domyślnej wartości dla jednego lub większej liczby argumentów. W ten sposób funkcja może zostać wywołana z mniejszą liczbą argumentów, niż była zdefiniowana, tzn.:
def zapytaj_ok(zacheta, liczba_prob=4, zazalenie='Tak lub nie, bardzo
proszę!'): while 1:
ok = raw_input(zacheta)
if ok in ('t', 'ta', 'tak'): return 1
if ok in ('n', 'nie', 'ee', 'gdzie tam'): return 0
liczba_prob = liczba_prob - 1
if liczba_prob < 0: raise IOError, 'użytkownik niekumaty'
print zazalenie
Funkcja ta może zostać wywołana w taki sposób:
zapytaj_ok('Naprawdę chcesz zakończyć?') lub w taki:
zapytaj_ok('Zgadzasz się nadpisać ten plik?', 2).
Wartości domyślne określane są w punkcie definicji funkcji, w przestrzeni definiowania nazw, tak więc np.:
i = 5 def f(arg = i): print arg i = 6 f()
wypisze 5.
Ważne ostrzeżenie: wartość domyślna określana jest tylko raz. Ma to znaczenie w przypadku, gdy wartością tą jest obiekt mutowalny, jak np. lista czy słownik. W przykładzie poniżej, funkcja akumuluje argumenty przekazane jej w kolejnych wywołaniach:
def f(a, l = []):
l.append(a)
return l
print f(1)
print f(2)
print f(3)
Instrukcje print spowodują:
[1] [1, 2] [1, 2, 3]
jeśli nie chce się, aby wartości domyślne były współdzielone pomiędzy kolejnymi wywołaniami funkcji, można ją napisać w taki sposób:
def f(a, l = None):
if l is None:
l = []
l.append(a)
return l
Funkcja może być wywołana z użyciem argumentów kluczowych, tzn. w formie "klucz = wartość". Na przykład, poniższa funkcja:
def papuga(napiecie, stan='racja', akcja='voom', typ='Norwegian Blue'):
print "-- Ta papuga nie zrobiłaby", akcja
print "jeśli przyłożysz", napiecie, "woltów do niej."
print "-- Śliczne upierzenie, ten", typ
print "-- Tak,", stan, "!"
mogłaby być wywołana na parę różnych sposobów:
papuga(1000)
papuga(akcja = 'VOOOOOM', napiecie = 1000000)
papuga('tysiąc', stan = 'już wącha kwiatki od spodu')
parrot('milion', 'bereft of life', 'skoku')
lecz poniższe wywołania byłyby nieprawidłowe:
papuga() # brakuje wymaganego argumentu papuga(napiecie=5.0, 'trup') # niekluczowy argument za kluczowym papuga(110, napiecie=220) # zduplikowana wartość argumentu papuga(aktor='John Cleese') # nieznana nazwa argumentu
W ogólności mówiąc,4.5lista argumentów wywołania, musi mieć jakiś argument pozycyjny, po którym następuje jakikolwiek argument kluczowy, gdzie klucze wybrane są z listy parametrów formalnych. Nie jest ważne, czy parametr formalny ma wartość domyślną, czy też nie. Żaden z argumentów nie może otrzymać wartości więcej niż jeden raz -- nazwy parametrów formalnych odpowiadające argumentom pozycyjnym w wywołaniu nie mogą być w nim użyte jako kluczowe. Oto przykład wywołania, które się nie powiedzie z uwagi na wymienione przed chwilą ograniczenia:
>>> def function(a): ... pass ... >>> function(0, a=0) Traceback (innermost last): File "<stdin>", line 1, in ? TypeError: keyword parameter redefined
Gdy na liście parametrów formalnych funkcji widnieje **nazwa, to
przy wywołaniu funkcji przypisywany jest mu słownik zawierający wszystkie
klucze, które nie odpowiadają nazwom parametrów formalnych. Mechanizm ten
może być połączony z wystąpieniem parametru formalnego o nazwie
*nazwa (co zostanie opisane w następnym podrozdziale), który w
momencie wywołania staje się krotką (ang. tuple), która
zawiera wszystkie argumenty pozycyjne (niekluczowe) wymienione w wywołaniu
funkcji za parametrami formalnymi. (*nazwa musi pojawić się przed
**nazwa na liście parametrów formalnych).
Jeżeli, na przykład, zdefiniujemy funkcję w ten sposób:
def sklep_z_serami(rodzaj, *argumenty, **klucze):
print "-- Czy macie", rodzaj, '?'
print "-- Przykro mi,", rodzaj, "właśnie się skończył."
for arg in argumenty: print arg
print '-'*40
for kl in klucze.keys(): print kl, ':', klucze[kl]
która mogłaby być wywołana o tak4.6:
sklep_z_serami('Limburger', "Jest bardzo dojrzały, proszę pana.",
"Jest naprawdę bardzo, BARDZO dojrzały, proszę pana.",
klient='John Cleese',
wlasciciel='Michael Palin',
skecz='Skecz ze sklepem z serami')
co oczywiście spowoduje wypisanie:
-- Czy macie Limburger ? -- Przykro mi, Limburger właśnie się skończył. Jest bardzo dojrzały, proszę pana. Jest naprawdę bardzo, BARDZO dojrzały, proszę pana. ---------------------------------------- klient : John Cleese wlasciciel : Michael Palin skecz : Skecz ze sklepem z serami
Ostatnim sposobem na to, aby funkcja została wywołana w dowolną liczbą argumentów jest wprost określenie tego w definicji. Wszystkie argumenty zostaną zapakowane w krotkę.4.7 Przedtem na liście argumentów może pojawić się zero lub więcej normalnych argumentów.
def fprintf(plik, format, *args):
plik.write(format % args)
Ze względu na wzrastającą liczbę głosów użytkowników, dodano do Pythona parę nowych właściwości spotykanych zwykle w językach funkcjonalnych. Za pomocą słowa kluczowego lambda możesz tworzyć małe, anonimowe (czyli nienazwane) funkcje. Oto funkcja, która zwraca sumę jej dwóch argumentów: "lambda a, b: a+b". Formy lambda mogą zostać użyte we wszystkich miejscach, gdzie wymagane są obiekty funkcji. Składniowo ograniczone są do pojedynczego wyrażenia. Semantycznie, są właściwie szczyptą cukru na składnię zwykłych definicji funkcji. Podobnie jak zagnieżdżone definicje funkcji, formy lambda nie mogą używać nazw zmiennych z zakresu zewnętrznego,, lecz może to być ominięte poprzez sprytne użycie argumentów domyślnych:
def stworz_powiekszacza(n):
return lambda x, incr=n: x+incr
Istnieje pewna konwencja dotycząca zawartości i formatowania napisów dokumentujących.
Pierwszy wiersz powinien być krótki, zwięźle podsumowujący działanie obiektu. Dla zwięzłości nie powinien wprost określać nazwy obiektu lub jego typu albowiem atrybuty te są dostępne dla czytelnika za pomocą innych środków (z wyjątkiem czasownika opisującego działanie funkcji). wiersz ten powien zaczynać się od dużej litery i kończyć kropką.
Jeśli napis zawiera więcej linii, drugi wiersz powinien być pusty, wizualnie oddzielając resztę opisu. Następne wiersze powinny obejmować jeden lub więcej akapitów, opisując sposób wywołania obiektu, efekty uboczne itd.
Parser Pythona nie wycina znaków tabulacji i wcięcia z wielowierszowych literałów napisów, dlatego też narzędzia do produkcji dokumentacji muszą to robić same, jeśli jest to wymagane. Robi się to wg następującej konwencji. Pierwszy niepusty wiersz po pierwszym wierszu napisu określa wielkość wsunięcia całego napisu dokumentującego. (Nie można użyć pierwszego wiersza, gdyż zazwyczaj położony jest bliżej otwierającego napis cydzysłowia, tak, że indentacja nie jest widoczna). Ekwiwalent tego wcięcia złożony z ,,białych znaków'' (czyli spacji, tabulacji) jest wycinany z początków wierszy całego napisu. Wiersze, które są wcięte mniej niż ta ilość, nie powinny się w napisie pojawić, ale jeśli to się stanie, to wszystkie znaki białe z przodu wiersza zostaną usunięte. Równowartość wcięcia liczona w spacjach powinna być sprawdzona po rozwinięciu znaków tabulacji (zazwyczaj do 8 spacji).
Oto przykład wielowierszowego docstring'u:
>>> def moja_funkcja():
... """Nie rób nic, ale udokumentuj to.
...
... Naprawdę, tutaj niczego się nie robi.
... """
... pass
...
>>> print moja_funkcja.__doc__
Nie rób nic, ale udokumentuj to.
Naprawdę, tutaj niczego się nie robi.