Informatika2-2014/Eloadas Python
Bevezetés a Python nyelvbe
Az előadáshoz elsőszámú olvasmány a Python tutorial.
A Pythont ismerjük a Sage-ből. Különbségek:
- ^ helyett ∗∗, / osztást, // egészosztást jelöl.
- [a..b] helyett range(a,b), vagy xrange(a,b)
- A megszokott, beépített matematikai függvények hiányoznak (find_root, plot, is_prime), de különböző modulokban sokuk megtalálható.
- Nincsenek szimbolikus változók
A Python egy olyan általános körben használható magas szintű programozási nyelv, aminek az egyik alapelve az olvasható kód írása egy nagyon tiszta szintaxis használatával. 1991-ben alkotta meg Guido Van Rossum.
További jellemzők
- objektum orientált, procedurális, funkcionális
- sok beépített modul a fejlesztés megkönnyítésére
- dinamikus típus kezelés
- automatikus memóriakezelés
- többféle megvalósítás (CPython, Jython, IronPython, PyPy, Python for S60)
- open-source a főbb platformokra
- sokkal tömörebb sok más nyelvnél
Nevét a Monthy Python ihlette, nem az állat.
Filozófiája megkapható a 'this' modul betöltésével:
import this
Python kód futtatása
Interaktív módon
Egyszerűen a python parancs terminálból indítva:
$ python Python 2.7.5+ (default, Sep 19 2013, 13:48:49) [GCC 4.8.1] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>
Fájlból
- Nyiss egy új file-t pl. a gedit-ben, mentsd el "kerdez.py" néven egy könyvtáradba!
- Írd bele a következő python kódot (ne használj ékezeteket):
s = input("Mondj egy szamot: ") print "Ennel eggyel kisebbet mondtal: ", s + 1
- Mentsd el, és futtasd a scriptedet! (python kerdez.py)
- Most kicsit kiegészítjük a scriptet, hogy tartalmazhasson ékezetes betűket, és hogy kényelmesebben futtatható legyen (a python parancs begépelése nélkül is):
#!/usr/bin/python #coding=UTF-8 s = input("Mondj egy számot: ") print "Ennél eggyel kisebbet mondtál: ", s + 1
- Mentsd el, és adj rá futtatási jogot csak magadnak (
chmod +x kerdez.py
)! - Futtasd így:
kerdez.py
vagy így:./kerdez.py
- A kód második sora lehet ez is:
# -*- coding: utf-8 -*-
Argumantum átadása
#!/usr/bin/env python #coding=utf-8 # Összead tetszőleges számú számot import sys # modul a rendszerfüggő információkhoz osszeg = sum(float(arg) for arg in sys.argv[1:]) print 'Összeg =', osszeg
Ha e fájl az osszeg.py nevű fájlba van mentve, akkor
$ ./osszeg.py 12 23.5 1 36.5
Kódolás stílusa
Stílus (code style) a PEP 8 alapján
- használj mindig 4 space-t minden egyes szinthez, de a folytatósort kezd még beljebb,
- a nagyobb kódrészeket tagold üres sorokkal (függvény, osztály, nagyobb kód blokk)
- használj space-t a vesző után és a legmagasabb szinten lévő operátorok körül
- használj docstring-et és ahol lehet a megjegyzés a saját sorára vonatkozzon, vagy azonos mértékben behúzva arra a blokkódra
- ahol lehet használj ASCII karakterkódolást
- 79 karakternél ne legyen hosszabb egy sor
- CamelCase elnevezési konvenciót kövesse az osztályok neve és lower_case_with_underscores a függvények és változók nevei
Érdemes megnézni a Google python code style ajánlását is.
Docstring
A hivatkozás nélküli string elemet szokás használni megjegyzések írására és dokumentálásra.
"""This is a class of example.
TODO: needs implementation.
"""
Első sort nagybetűvel kezdjük és pontal zárjuk. Egy összefoglaló mondat legyen. Majd egy üres sort hagyva részletesen leírhatunk minden funkciót amit az osztály vagy függvény tartalmaz. Megadhatjuk, hogy a függvény bizonyos hívásaira mi legyen a válasz,
Hasznos linkek:
#coding=utf-8 def lnko(a, b): """Kiszámolja két szám legnagyobb közös osztóját. >>> lnko(36, 8) 4 >>> lnko(-36, 4) 4 >>> lnko(3, 0) 3 """ a, b = abs(a), abs(b) while a != 0: a, b = b%a, a return b if __name__ == "__main__": import doctest doctest.testmod()
Ha lnko.py
a neve, akkor egy
python lnko.py
parancs után nem kapunk semmit (mert a teszt hiba nélkül lefutott), azonban a -v opciót is használva látjuk a részleteket is:
$ python lnko.py -v Trying: lnko(36, 8) Expecting: 4 ok Trying: lnko(-36, 4) Expecting: 4 ok Trying: lnko(3, 0) Expecting: 3 ok 1 items had no tests: __main__ 1 items passed all tests: 3 tests in __main__.lnko 3 tests in 2 items. 3 passed and 0 failed. Test passed.
A Python, mint számológép
Azonosítók
Az adatokat többszöri felhasználásra azonosítóval (névvel) láthatjuk el.
- a név betűvel vagy aláhúzással kezdődhet: [_a-zA-Z]
- a név további karakterei az előbbieken felül számok is lehetnek: [_a-zA-Z0-9]
- elméletileg bármilyen hosszú lehet a név
- név nem lehet foglalt szó
- nagybetű-kisbetű érzékeny, tehát a val1 név nem azonos a Val1 névvel
Másképp, Backus–Naur formában leírva:
identifier ::= (letter|"_") (letter | digit | "_")* letter ::= lowercase | uppercase lowercase ::= "a"..."z" uppercase ::= "A"..."Z" digit ::= "0"..."9"
A foglalt szavak:
and del from not while
as elif global or with
assert else if pass yield
break except import print
class exec in raise
continue finally is return
def for lambda try
De ne használjuk a Python beépített neveinek, függvényeinek, kivételeinek neveit sem. Ezek megkaphatók a dir(__builtins__)
paranccsal:
>>> dir() ['__builtins__', '__doc__', '__name__', '__package__'] >>> dir(__builtins__) ['ArithmeticError', 'AssertionError', ......
Egész szerű adattípusok: egész (int, long), logikai (bool)
int (egész) és hosszú egész (long)
>>> a = 12 >>> b = 0b011101 >>> c = 0o3701 >>> d = 0xff0c >>> a, b, c, d (12, 29, 1985, 65292) >>> e = 22222222222222222222222222222222222222222 >>> e 22222222222222222222222222222222222222222L >>> type(a), type(b), type(e) (<type 'int'>, <type 'int'>, <type 'long'>)
Műveletek egészekkel: +, -, *, / (float eredményt ad), //, % (maradék), **, abs, pow, round, | (OR butenként), ^ (XOR bitenként), & (AND bitenként), <<, >> (eltolás bitenként), ~ (bitenkénti NOT)
Logikai (bool) típus:
Logikai értékek: False (0 vagy 0 hosszúságú), True (nem 0 vagy nem 0 hosszúságú)
Logikai műveletek: and, or, not
>>> True and False False >>> 1 and 0 0 >>> 3 and 0 0 >>> 3 or 1 3 >>> 1 or 3 1 >>> not 67 False >>> not 0 True
Beépített lebegőpontos típusok (float, complex)
Lebegőpontos szám megadása:
>>> 2.3, -1.2e3, -1.2e-2 (2.2999999999999998, -1200.0, -0.012)
Matematikai függvények:
import math
után. Ld. [1]
Komplex szám imaginárius része után j betű, de * nincs! Komplex jellemzői (attribute) a real és az imag, tagfüggvénye (method) conjugate():
>>> z = 3.1 + 2.2j >>> z (3.1000000000000001+2.2000000000000002j) >>> z.real 3.1000000000000001 >>> z.imag 2.2000000000000002 >>> z.conjugate() (3.1000000000000001-2.2000000000000002j)
Karakterláncok (str)
A karakterláncok megadása: "...", '...' vagy """...""" módon történhet:
>>> a="""itt 'ez' meg "az" van""" >>> a 'itt \'ez\' meg "az" van' >>> print a itt 'ez' meg "az" van >>> type(a) <type 'str'> >>> c = 'aa\nbb' >>> c 'aa\nbb' >>> print c aa bb >>> d = r'aa\nbb' # az r betű után minden karakter magát jelenti >>> d 'aa\\nbb' >>> print d aa\nbb
Védőkódok (eszkép karakterek, escape characters): \ (folytatás új sorban), \\ (\), \' ('), \" ("), \n (új sor), \t (tab). Ha a karakterlánc elé r betűt írunk, a védőkódok nem érvényesek.
Műveletek karakterláncokkal: indexelés és szeletelés:
lánc[sorszám] lánc[kezdet:vég] lánc[kezdet:vég:lépés]
továbbá az + (összefűzés) és a * (többszörözés) műveletek:
>>> a = "ho" >>> b = "rgasz" >>> 3*a + b 'hohohorgasz' >>> c = _ # _ az előző eredmény >>> c 'hohohorgasz' >>> c[:2]+c[6:] 'horgasz' >>> c[1:7:2] 'ooo' >>> c[1:6:2] 'ooo' >>> c[-1::-1] 'zsagrohohoh' >>> c[-3:4:-1] 'agro'
Az indexekre kétféleképp gondolhatunk: 1. a második index már nincs (ennek pl. az az értelme, hogy egy intervallum végét, és a következő elejét azonos érték jelzi, nem kell 1-et hozzáadni), 2. az indexeket az elemek közé képzeljük, vagyis az elemek határait indexeljük:
+---+---+---+---+---+---+---+ | h | o | r | g | a | s | z | +---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 -5 -6 -5 -4 -3 -2 -1
Metódusok (tagfüggvények, methods): részletesen lásd [2]. Folytatva az előző példát:
>>> c.capitalize() 'Hohohorgasz' >>> c.upper() 'HOHOHORGASZ' >>> c.index('o') 1 >>> c.count('o') 3
A karakterláncok nem változtatható (immutable) objektumok, vagyis a műveletek, tagfüggvények alkalmazása után új karakterlánc keletkezik:
>>> a = "aaaa" >>> a[1] = b Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'str' object does not support item assignment
Objektumhivatkozások
Az értékadás (=) esetén valójában objektumhivatkozás történik, azaz az egyenlőség bal oldalán álló névhez egy hivatkozás kapcsolódik, mely az egyenlőség jobb oldalán álló objektumra mutat. Ez érthetővé teszi a következő kódot:
>>> a = 1 >>> b = a >>> a = 2 >>> a 2 >>> b 1
A Python dinamikusan típusos nyelv, azaz az objektum, amire egy objektumhivatkozás mutat, lecserélhető egy más típusú objektumra (nem kell a változók típusát deklarálni).
>>> a = 1 >>> type(a) <type 'int'> >>> a = "b" >>> type(a) <type 'str'>
Azonossági művelet
Az alábbi példában a és b még azonos, mert ugyanarra az objektumra hivatkoznak, de a c és d már nem azonosak, bár egyenlők:
>>> a = 2 >>> b = 2 >>> a is b True >>> c = [1, 2, 3] >>> d = [1, 2, 3] >>> c is d False >>> c == d True
Összehasonlító műveletek
Nem csak a számok, de karakterláncok, sorozatok, listák... is összehasonlíthatók (==, !=, <, >, <=, >=):
>>> a = 23 >>> b = 56 >>> a == b False >>> a != b True >>> a <= b True >>> c = "abc" >>> d = "abcd" >>> c == d[:3] True >>> c < d True >>> (2, 1, 3) <= (2, 1, 4) True
Tagsági műveletek
in, not in:
>>> l = [1, 2, "cica"] >>> 2 in l True >>> "macska" not in l True >>> "c" in l[2] True >>> "ci" in l[2] True >>> "ci" in l False
Listák
Ugyanúgy lehet szeletelni (slice), összeadni, többszörözni, mint a karakterláncot, de a lista változtatható (mutable):
>>> x = [1, 2, 3, 4] >>> x[:2]*2 + x[-1:] [1, 2, 1, 2, 4] >>> x[:2]*2 + x[-1] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate list (not "int") to list >>> x[0::2] [1, 3] >>> x[-1::-1] [4, 3, 2, 1]
Az értékadás (=) csak objektumhivatkozással jár, nem történik adatmásolás. Ennek következtében egy y = x
parancs után, ahol x lista (vagy valamilyen más gyűjteményes adattípus), az y ugyanarra az objektumra fog mutatni. Így ha megváltoztatjuk x-et vagy y-t, változik a másik is. Az objektumhivatkozások megtörténhetnek egy szinttel mélyebben is, a (z = x[:]
kód esetén az x elemeire mutató hivatkozások másolódnak, de ekkor sem jön létre a teljes objektumról másolat. Ezt hívjuk
sekély másolásnak (shallow copy).
Egy másik példa sekély másolásra:
Mély másolás (deep copy), amikor valóban új példány keletkezik az objektumból:
import copy w = copy.deepcopy(x)
Lista létrehozása, listaértelmezés (list comprehension)
Lista létrehozható értékadással, [] az üres lista. A range parancs is listát ad vissza:
>>> range(3) [0, 1, 2] >>> range(3, 6) [3, 4, 5] >>> range(1,10,3) [1, 4, 7]
Rövid listák létrehozásának egyszerű módja a listaértelmezés. Általános alakja:
[expression for expr in sequence1 if condition1 for expr2 in sequence2 if condition2 ... for exprN in sequenceN if conditionN]
Kis programrészek helyettesíthetők vele. Például soroljuk fel az 1890 és 1915 közé eső szökőéveket!
szoko = [] for ev in range(1890, 1922): if (ev%4 == 0 and ev%100 != 0) or (ev%400 == 0): szoko.append(ev) print szoko [1892, 1896, 1904, 1908, 1912, 1916, 1920]
Lépésenként egyre összetettebb listaértelmezéssel állítsuk elő ugyanezt:
>>> szoko = [ev for ev in range(1890, 1915)] >>> szoko # ez még az összes év [1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914] >>> szoko = [ev for ev in range(1890, 1915) if ev%4 == 0] >>> szoko # ez a 4-gyel osztható évek listája [1892, 1896, 1900, 1904, 1908, 1912] >>> szoko = [ev for ev in range(1890, 1915) if (ev%4 == 0 and ev%100 != 0) or ev%400 == 0] >>> szoko [1892, 1896, 1904, 1908, 1912]
Egy egyszerű algoritmus egy különböző elemekből álló lista összes permutációja listájának előállítására:
def perm(lista): if lista: return [[x] + p for x in lista for p in perm([y for y in lista if y != x])] else: return [[]]
Például:
>>> perm([]) [[]] >>> perm([1, 2, 3]) [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
* Egy nehezebb feladat: Tegyünk fel nyolc vezért egy sakktáblára úgy, hogy semelyik kettő ne üsse egymást! Soroljuk fel az összes ilyen vezérelhelyezést!
Az ilyen bástyaelhelyezések száma 8! = 40320. A vezérek (királynők) azonban átlósan is üthetik egymást. Legyen x egy permutációja a [0, 1, 2, 3, 4, 5, 6, 7] számoknak. Az i-edik sorban a vezér legyen az x[i]-edik oszlopban. Az i-edik és j-edik sorban lévő vezér pontosan akkor üti egymást, ha abs(i - j) != abs(x[i] - x[j]). A permutációk listázásához töltsük be az itertools csomag permutations függvényét, mely a for ciklus minden ciklusában ad egy következő permutációt, amíg a végére nem ér (így nem kell felsorolni mind a 8! permutációt egyetlen listában). Az all függvény igaz, ha az argumentumában lévő lista minden eleme igaz. Így a megoldás:
from itertools import permutations for x in permutations(range(8)): if all([abs(i - j) != abs(x[i] - x[j]) for i in range(8) for j in range(i)]): print x
Egy logikai feladat
Sokan Einsteinnek tulajdonítják, de erre semmi bizonyíték nincs, sőt, a feladat szövege alapján szinte biztos, hogy nem tőle származik. Angol alapváltozatának neve ,,Zebra puzzle".
Az elterjedt magyar változat a következő: Van 5 különböző színű ház. Minden házban él egy-egy ember, mindegyik más nemzetiségű. Az öt tulajdonos különböző italt fogyaszt, különféle cigit szív és más-más állatot tart, mindegyikből pontosan egyet.
- A skót a piros házban lakik.
- A svéd kutyát tart.
- A dán teát iszik.
- A zöld ház a fehér ház bal oldalán van.
- A zöld ház tulajdonosa kávét iszik.
- Az a személy aki Pall Mall-t szív madarat tart.
- A sárga ház tulajdonosa Dunhill-t szív.
- Az az ember aki a középső házban lakik tejet iszik.
- A norvég az első házban lakik.
- Az ember aki Blend cigit szív amellett lakik aki macskát tart.
- Az az ember aki lovat tart amellett lakik aki Dunhill cigit szív.
- A tulaj aki Blue Mastert szív, sört iszik.
- A német Prince-t szív.
- A norvég a kék ház mellett lakik.
- Az ember aki Blend-et szív, a vizet ivó ember szomszédja.
A kérdés: Melyik tart halat és ki iszik vizet?
Írjunk programot, mely megválaszolja e kérdést, gyorsan lefut. Igazoljuk, hogy a magyar változat gyengéje, hogy az utolsó feltétel elhagyható, úgy is csak egy megoldás van. Hogyan változik a megoldás, ha a 4. feltételben kicseréljük a két házat?
Az előző perm algoritmust használó megoldás, ami becslésünk szerint több órát fut:
def jobbra(h1, h2): return h1 - h2 == 1 def szomszed(h1, h2): return abs(h1 - h2) == 1 sorrend = perms([1, 2, 3, 4, 5]) print [(skot, sved, dan, nemet, norveg, hal, viz) for [piros, zold, feher, sarga, kek] in sorrend for [skot, sved, dan, nemet, norveg] in sorrend for [kave, tea, tej, sor, viz] in sorrend for [PallMall, Dunhill, Blend, BlueMaster, Prince] in sorrend for [kutya, madar, macska, lo, hal] in sorrend if skot is piros # 1 if sved is kutya # 2 if dan is tea # 3 if jobbra(zold, feher) # 4 if kave is zold # 5 if PallMall is madar # 6 if Dunhill is sarga # 7 if tej is 3 # 8 if norveg is 1 # 9 if szomszed(Blend, macska) #10 if szomszed(Dunhill, lo) #11 if BlueMaster is sor #12 if nemet is Prince #13 if szomszed(norveg, kek) #14 if szomszed(Blend, viz) #15 ]
Javított változat:
sorrend = perms([1, 2, 3, 4, 5]) print [(skot, sved, dan, nemet, norveg, hal, viz) for [piros, zold, feher, sarga, kek] in sorrend if jobbra(zold, feher) # 4 for [skot, sved, dan, nemet, norveg] in sorrend if skot is piros # 1 if norveg is 1 # 9 if szomszed(norveg, kek) #14 for [kave, tea, tej, sor, viz] in sorrend if dan is tea # 3 if kave is zold # 5 if tej is 3 # 8 for [PallMall, Dunhill, Blend, BlueMaster, Prince] in sorrend if Dunhill is sarga # 7 if BlueMaster is sor #12 #if szomszed(Blend, viz) #15 for [kutya, madar, macska, lo, hal] in sorrend if sved is kutya # 2 if PallMall is madar # 6 if szomszed(Blend, macska) #10 if szomszed(Dunhill, lo) #11 if nemet is Prince #13 ]
Operátorok precedenciája
Az operátorok között, mint a matematikában itt is, van precedencia sorrend:
Operator | Description |
---|---|
lambda | Lambda expression |
if – else | Conditional expression |
or | Boolean OR |
and | Boolean AND |
not x | Boolean NOT |
in, not in, is, is not, <, <=, >, >=, <>, !=, == | Comparisons, identity test, including membership test |
| | Bitwise OR |
^ | Bitwise XOR |
& | Bitwise AND |
<<, >> | Shifts |
+, -
|
Addition and subtraction |
*, //, /, % | Multiplication, division, remainder |
+x, -x, ~x
|
Positive, negative, bitwise not |
** | Exponentiation |
x[index], x[index:index], x(arguments...), x.attribute | Subscription, slicing, call, attribute reference |
(expressions...), [expressions...], {key:datum...}, `expressions...` | Binding or tuple display, list display, dictionary display, string conversion |
A sage, python a kifejezéseket balról jobbra értékeli ki, kivéve az értékadásnál, amikor előbb a jobb oldalt értékeli ki, majd a bal oldalt. Pl. a logikai kifejezés elemeit ha mar felesleges nem értékeli ki.
A procedurális programozás elemei
Vezérlő utasítások
if
>>> x = int(raw_input("Adj meg egy egész számot: ")) Adj meg egy egész számot: 42 >>> if x < 0: ... print "ez negatív" ... elif x == 0: ... print "ez nulla" ... elif x == 1: ... print "ez egy" ... else: ... print "ez sok" ... ez sok
Az elif-ek száma tetszőleges, és ezzel elkerülhető a sok behúzás.
A következő kóddal tesztelhető, hogy milyen kifejezéseket tekint a python igaznak:
x = 5 y = 5.0 if x == y: # if x is 5: # True, 1, 2, 0.00001, [[]], ((),), print "igaz, nem 0" else: # False, None, 0, 0.0, 0 + 0j, [], (), (()), {} print "hamis, 0, a hossza 0"
for, break, else, continue
>>> long_words = [u"Antidisestablishmentarianism", u"Donaudampfschiffahrtselektrizitätenhauptbetriebswerkbauunterbeamtengesellschaft", u"bejelentkezésszabályozási", u"fosszilisdinoszauruszhányásvilágranglista-megdöntés", u"folyamatellenőrzésiügyosztályvezetőhelyettesképesítésvizsgálat-szervezéseitekkel"] >>> for i in long_words: ... print i, len(i) ... Antidisestablishmentarianism 28 Donaudampfschiffahrtselektrizitätenhauptbetriebswerkbauunterbeamtengesellschaft 79 bejelentkezésszabályozási 25 fosszilisdinoszauruszhányásvilágranglista-megdöntés 51 folyamatellenőrzésiügyosztályvezetőhelyettesképesítésvizsgálat-szervezéseitekkel 80
Döntsük el 10-ig minden egészről, hogy prím vagy összetett szám!
>>> for n in range(2, 10): ... for x in range(2, n): ... if n % x == 0: ... print n, '=', x, '*', n/x ... break ... else: ... # ha a ciklusban nem talált osztót (nem volt break) ... print n, 'prím' ... 2 prím 3 prím 4 = 2 * 2 5 prím 6 = 2 * 3 7 prím 8 = 2 * 4 9 = 3 * 3
Az else a for-ral is használható! Szerencsétlen a névhasználat (jobb lenne pl. finally), de a szerkezet praktikus lehet. Az else ágra a ciklus utolsó végrehajtása után kerül a vezérlés (így akkor is, ha a ciklus egyszer sem fut le). Elkerüli viszont az else ágat a vezérlés, ha a break utasítással hagyjuk el a ciklust.
Írjuk ki az 50 alatti páros számokat, de a 3-mal oszthatók helyett *-ot tegyünk!
>>> for n in range(2, 50, 2): ... if n % 3 == 0: ... print "*", ... continue ... print n, ... 2 4 * 8 10 * 14 16 * 20 22 * 26 28 * 32 34 * 38 40 * 44 46 *
while, braek, else
Írjuk ki az 1000 alatti Fibonacci-számokat:
>>> n = 1000 >>> a, b = 0, 1 >>> while a < n: ... print a, # a vessző miatt egy sorba kerülnek ... a, b = b, a + b ... 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
A while-nak is lehet else-ága és használható a break.
A pythonban nincs hátul tesztelő ciklusutasítás, a következővel helyettesíthető:
while True: utasítások if kilépési_feltétel: break (utasítások)
pass
Nem csinál semmit, ami sokszor nagyon jól jöhet:
while True: pass # Várunk egy billentyűzet interruptot (Ctrl+C)
def func(*args): pass # megírandó
Függvények
Opcionálisan megadható argumentumok alapértelmezett értékkel
def ask_ok(prompt, retries=4, complaint='Yes or no, please!'): while True: ok = raw_input(prompt) if ok[0] in ('y', 'Y', 'i', 'I'): return True if ok[0] in ('n', 'N'): return False retries = retries - 1 if retries < 0: raise IOError('refusenik user') print complaint
Néhány lehetséges meghívása:
ask_ok("Is it OK? ") ask_ok("May I delete your files? ", 0) ask_ok("Törölhetem a wincsesztert? ", 1, "Igen vagy nem? ")
Az alapértelmezett argumentum értéke a függvény létrehozásakor lesz kiszámolva, nem a meghívásakor! És csak akkor egyszer! Ez a változtatható (mutable) objektumoknál érdekes hatással jár:
def f(a, L=[]): L.append(a) return L print f(1) print f(2) print f(5)
A futás eredménye:
[1] [1, 2] [1, 2, 5]
E mellékhatás elkerülésére [] helyett None-t használjunk!
def f(a, L=None): if L is None: L = [] L.append(a) return L
Az argumentumok megadhatók kulcsszó = érték alakban a kötelező argumentumok esetén is. Így az argumentumok sorrendje is megváltoztatható,