|
|
(egy szerkesztő 44 közbeeső változata nincs mutatva) |
1. sor: |
1. sor: |
− | =Bevezetés a Python nyelvbe= | + | === Dekorátor === |
| | | |
− | Az előadáshoz elsőszámú olvasmány a [http://docs.python.org/2.7/tutorial/ Python tutorial].
| + | Jó leírások: [[http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/]], [[http://www.artima.com/weblogs/viewpost.jsp?thread=240808]] |
| | | |
− | A Pythont ismerjük a Sage-ből. | + | A '''dekorátorok''' módosítják függvények vagy osztályok kódját! |
− | 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 [http://en.wikipedia.org/wiki/Guido_van_Rossum Guido Van Rossum.]
| + | ==== Scope (hatókör), névtér ==== |
| | | |
− | További jellemzők
| + | Minden új függvény fölépíti saját névterét, egy szótár formájában. Íme a globális és egy lokális névtér: |
− | * 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:
| |
− |
| |
− | <bash>
| |
− | $ 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.
| |
− | >>>
| |
− | </bash>
| |
− |
| |
− | === 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):
| |
| <python> | | <python> |
− | s = input("Mondj egy szamot: ")
| + | >>> x = 2 |
− | print "Ennel eggyel kisebbet mondtal: ", s + 1
| + | >>> print globals() |
− | </python> | + | {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'x': 2, '__doc__': None, '__package__': None} |
− | * Mentsd el, és futtasd a scriptedet! (''python kerdez.py'')
| + | >>> def fn(): |
− | * 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):
| + | ... y = 3 |
− | <python>
| + | ... print locals() |
− | #!/usr/bin/python
| + | ... |
− | #coding=UTF-8
| + | >>> fn() |
− | s = input("Mondj egy számot: ")
| + | {'y': 3} |
− | print "Ennél eggyel kisebbet mondtál: ", s + 1
| + | |
− | </python>
| + | |
− | * Mentsd el, és adj rá futtatási jogot csak magadnak (<code>chmod +x kerdez.py</code>)!
| + | |
− | * Futtasd így: <code>kerdez.py</code> vagy így: <code>./kerdez.py</code>
| + | |
− | * A kód második sora lehet ez is:
| + | |
− | <python>
| + | |
− | # -*- coding: utf-8 -*-
| + | |
| </python> | | </python> |
| | | |
− | === Argumantum átadása ===
| + | Ha egy név lokálisan nem lett létrehozva, a tartalmazó névterekben keresi egyre kijjebb haladva (itt az x nem lett lokálisan létrehozva, de elérhető): |
| | | |
| <python> | | <python> |
− | #!/usr/bin/env python
| + | >>> def fn(): |
− | #coding=utf-8
| + | ... y = 3 |
− | # Összead tetszőleges számú számot
| + | ... print "x, y:", x, y |
− | import sys # modul a rendszerfüggő információkhoz
| + | ... print locals() |
− | | + | ... |
− | osszeg = sum(float(arg) for arg in sys.argv[1:])
| + | >>> fn() |
− | print 'Összeg =', osszeg
| + | x, y: 2 3 |
| + | {'y': 3} |
| </python> | | </python> |
| | | |
− | Ha e fájl az osszeg.py nevű fájlba van mentve, akkor
| + | Kérdés: Mi történik az alábbi kód hatására? magyarázzuk meg, mi történik: |
| | | |
− | <bash>
| |
− | $ ./osszeg.py 12 23.5 1
| |
− | 36.5
| |
− | </bash>
| |
− |
| |
− | == Kódolás stílusa ==
| |
− |
| |
− | Stílus (code style) a [http://www.python.org/dev/peps/pep-0008 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 [http://google-styleguide.googlecode.com/svn/trunk/pyguide.html 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.
| |
| <python> | | <python> |
− | """This is a class of example. | + | >>> def fn(): |
− | | + | ... y = 3 |
− | TODO: needs implementation.
| + | ... print "x, y:", x, y |
− | """
| + | ... x = 5 |
| + | ... print locals() |
| + | ... |
| + | >>> fn() |
| </python> | | </python> |
− | 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:
| + | És mi történik, ha a 3. és 4. sort fölcseréljük? |
− | * [http://www.python.org/dev/peps/pep-0257/ hogyan érdemes használni a docstringet]
| + | |
− | * [http://docs.python.org/library/doctest.html tesztelés docstring segítségével]
| + | |
| | | |
− | <Python>
| + | A névtér törlődik a függvény lefutása után, magasabb szinten az alacsonyabb szintű névterek nem érhetők el: |
− | #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()
| |
− | </Python>
| |
− |
| |
− | Ha <code>lnko.py</code> a neve, akkor egy
| |
− | <bash>
| |
− | python lnko.py
| |
− | </bash>
| |
− | 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:
| |
− | <bash>
| |
− | $ 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.
| |
− | </bash>
| |
− |
| |
− |
| |
− | == 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:
| |
− | <bnf>
| |
− | identifier ::= (letter|"_") (letter | digit | "_")*
| |
− | letter ::= lowercase | uppercase
| |
− | lowercase ::= "a"..."z"
| |
− | uppercase ::= "A"..."Z"
| |
− | digit ::= "0"..."9"
| |
− | </bnf>
| |
− |
| |
− | A foglalt szavak:
| |
− | <code>
| |
− | 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
| |
− | </code>
| |
− | De ne használjuk a Python beépített neveinek, függvényeinek, kivételeinek neveit sem. Ezek megkaphatók a <code>dir(__builtins__)</code> paranccsal:
| |
− | <Python>
| |
− | >>> dir()
| |
− | ['__builtins__', '__doc__', '__name__', '__package__']
| |
− | >>> dir(__builtins__)
| |
− | ['ArithmeticError', 'AssertionError', ......
| |
− | </Python>
| |
− |
| |
− | === Egész szerű adattípusok: egész (int, long), logikai (bool) ===
| |
− |
| |
− | '''int (egész) és hosszú egész (long)'''
| |
| <python> | | <python> |
− | >>> a = 12 | + | >>> def fn(): |
− | >>> b = 0b011101
| + | ... z = 1 |
− | >>> c = 0o3701
| + | ... |
− | >>> d = 0xff0c
| + | >>> print z |
− | >>> a, b, c, d
| + | |
− | (12, 29, 1985, 65292) | + | |
− | >>> e = 22222222222222222222222222222222222222222
| + | |
− | >>> e
| + | |
− | 22222222222222222222222222222222222222222L
| + | |
− | >>> type(a), type(b), type(e)
| + | |
− | (<type 'int'>, <type 'int'>, <type 'long'>)
| + | |
− | </python>
| + | |
− | | + | |
− | 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
| + | |
− | | + | |
− | <python>
| + | |
− | >>> 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
| + | |
− | </python>
| + | |
− | | + | |
− | === Beépített lebegőpontos típusok (float, complex) ===
| + | |
− | | + | |
− | <!-- WF: PÉLDÁT IDE: A műveletek eredménye NaN (not a number) és infinity is lehet! -->
| + | |
− | | + | |
− | '''Lebegőpontos''' szám megadása:
| + | |
− | <python>
| + | |
− | >>> 2.3, -1.2e3, -1.2e-2
| + | |
− | (2.2999999999999998, -1200.0, -0.012)
| + | |
− | </python>
| + | |
− | Matematikai függvények:
| + | |
− | <python>
| + | |
− | import math
| + | |
− | </python>
| + | |
− | után. Ld. [http://docs.python.org/2/library/math.html]
| + | |
− | | + | |
− | '''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():
| + | |
− | <python>
| + | |
− | >>> z = 3.1 + 2.2j
| + | |
− | >>> z
| + | |
− | (3.1000000000000001+2.2000000000000002j)
| + | |
− | >>> z.real
| + | |
− | 3.1000000000000001
| + | |
− | >>> z.imag
| + | |
− | 2.2000000000000002
| + | |
− | >>> z.conjugate()
| + | |
− | (3.1000000000000001-2.2000000000000002j)
| + | |
− | </python>
| + | |
− | | + | |
− | === Karakterláncok (str) ===
| + | |
− | | + | |
− | '''A karakterláncok megadása''': "...", '...' vagy """...""" módon történhet:
| + | |
− | <python>
| + | |
− | >>> 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
| + | |
− | </python>
| + | |
− | | + | |
− | '''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:
| + | |
− | <python>
| + | |
− | lánc[sorszám]
| + | |
− | lánc[kezdet:vég]
| + | |
− | lánc[kezdet:vég:lépés]
| + | |
− | </python>
| + | |
− | továbbá az '''+''' (összefűzés) és a '''*''' (többszörözés) műveletek:
| + | |
− | <python>
| + | |
− | >>> 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'
| + | |
− | </python>
| + | |
− | | + | |
− | 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:
| + | |
− | | + | |
− | <bash>
| + | |
− | +---+---+---+---+---+---+---+
| + | |
− | | h | o | r | g | a | s | z |
| + | |
− | +---+---+---+---+---+---+---+
| + | |
− | 0 1 2 3 4 5 6 7
| + | |
− | -5 -6 -5 -4 -3 -2 -1
| + | |
− | </bash>
| + | |
− | | + | |
− | Metódusok (tagfüggvények, methods): részletesen lásd
| + | |
− | [http://docs.python.org/release/2.5.2/lib/string-methods.html]. Folytatva az előző példát:
| + | |
− | <python>
| + | |
− | >>> c.capitalize()
| + | |
− | 'Hohohorgasz'
| + | |
− | >>> c.upper()
| + | |
− | 'HOHOHORGASZ'
| + | |
− | >>> c.index('o')
| + | |
− | 1
| + | |
− | >>> c.count('o')
| + | |
− | 3
| + | |
− | </python>
| + | |
− | | + | |
− | '''A karakterláncok nem változtatható (immutable) objektumok''', vagyis a műveletek, tagfüggvények alkalmazása után új karakterlánc keletkezik:
| + | |
− | <python>
| + | |
− | >>> a = "aaaa"
| + | |
− | >>> a[1] = b
| + | |
| Traceback (most recent call last): | | Traceback (most recent call last): |
| File "<stdin>", line 1, in <module> | | File "<stdin>", line 1, in <module> |
− | TypeError: 'str' object does not support item assignment
| + | NameError: name 'z' is not defined |
| </python> | | </python> |
| | | |
− | | + | A '''függvény lezárása''' a Pythonnak azt a képességét jelenti, hogy a nem globális névtérben definiált függvény '''emlékszik''' a definiálás pillanatában érvényes bennfoglaló névterekre: |
− | === 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:
| + | |
− | <python>
| + | |
− | >>> a = 1
| + | |
− | >>> b = a
| + | |
− | >>> a = 2
| + | |
− | >>> a
| + | |
− | 2
| + | |
− | >>> b
| + | |
− | 1
| + | |
− | </python>
| + | |
− | 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). | + | |
− | <python>
| + | |
− | >>> a = 1
| + | |
− | >>> type(a)
| + | |
− | <type 'int'>
| + | |
− | >>> a = "b"
| + | |
− | >>> type(a)
| + | |
− | <type 'str'>
| + | |
− | </python>
| + | |
− | | + | |
− | ==== 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:
| + | |
− | <python>
| + | |
− | >>> a = 2
| + | |
− | >>> b = 2
| + | |
− | >>> a is b
| + | |
− | True
| + | |
− | >>> c = [1, 2, 3]
| + | |
− | >>> d = [1, 2, 3]
| + | |
− | >>> c is d
| + | |
− | False
| + | |
− | >>> c == d
| + | |
− | True
| + | |
− | </python>
| + | |
− | | + | |
− | ==== Összehasonlító műveletek ====
| + | |
− | | + | |
− | Nem csak a számok, de karakterláncok, sorozatok, listák... is összehasonlíthatók (==, !=, <, >, <=, >=):
| + | |
− | <python>
| + | |
− | >>> 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
| + | |
− | </python>
| + | |
− | | + | |
− | ==== Tagsági műveletek ====
| + | |
− | | + | |
− | in, not in:
| + | |
− | <python>
| + | |
− | >>> 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
| + | |
− | </python>
| + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | === Listák ===
| + | |
− | | + | |
− | Ugyanúgy lehet '''szeletelni (slice)''', összeadni, többszörözni, mint a karakterláncot, de '''a lista változtatható (mutable)''':
| + | |
− | | + | |
− | <python>
| + | |
− | >>> 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]
| + | |
− | </python>
| + | |
− | | + | |
− | Objektumhivatkozás átadása, és '''sekély másolás (shallow copy)''', azaz a belső szinteken nem történik másolás, csak a hivatkozások másolódnak.
| + | |
− | Az értékadás (=) csak objektumhivatkozással jár, nem történik adatmásolás. Ennek következtében egy <code>y = x</code> 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 (<code>z = x[:]</code> 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)'''.
| + | |
− | | + | |
− | | + | |
− | <wikiframe width="800" frameborder="0" src="http://pythontutor.com/iframe-embed.html#code=x+%3D+%5B0,+%5B4,+5%5D,+3%5D%0Ay+%3D+x+++++++%23+hivatkoz%C3%A1s%0Az+%3D+x%5B%3A%5D++++%23+sek%C3%A9ly+m%C3%A1sol%C3%A1s+(shallow+copy)%0Ay%5B1%5D+%3D+1%0Az%5B1%5D+%3D+2%0Aprint+%22x+%3D%22,+x%0Aprint+%22y+%3D%22,+y%0Aprint+%22z+%3D%22,+z%0A&cumulative=false&heapPrimitives=false&drawParentPointers=false&textReferences=false&showOnlyOutputs=false&py=2&curInstr=0&codeDivWidth=350&codeDivHeight=400"> </wikiframe>
| + | |
− | | + | |
− | Egy másik példa sekély másolásra:
| + | |
− | | + | |
− | <wikiframe width="800" height="500" frameborder="0" src="http://pythontutor.com/iframe-embed.html#code=x+%3D+%5B1,+2,+%5B%22a%22,+%22b%22%5D%5D%0Ay+%3D+x%0Az+%3D+x%5B%3A%5D%0Ay%5B0%5D+%3D+0%0Aprint+x,+y,+z%0Az%5B0%5D+%3D+5%0Aprint+x,+y,+z%0Ax%5B2%5D%5B0%5D+%3D+%22X%22%0Aprint+x,+y,+z%0A&cumulative=false&heapPrimitives=false&drawParentPointers=false&textReferences=false&showOnlyOutputs=false&py=2&curInstr=0&codeDivWidth=350&codeDivHeight=400"> </wikiframe>
| + | |
− | | + | |
− | '''Mély másolás (deep copy)''', amikor valóban új példány keletkezik az objektumból:
| + | |
− | <python>
| + | |
− | import copy
| + | |
− | w = copy.deepcopy(x)
| + | |
− | </python>
| + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | A range parancs is listát ad vissza:
| + | |
− | <python>
| + | |
− | >>> range(3)
| + | |
− | [0, 1, 2]
| + | |
− | >>> range(3, 6)
| + | |
− | [3, 4, 5]
| + | |
− | >>> range(1,10,3)
| + | |
− | [1, 4, 7]
| + | |
− | </python>
| + | |
− | | + | |
− | | + | |
− | === Lista létrehozása, listaértelmezés (list comprehension) ===
| + | |
− | | + | |
− | Rövid listák létrehozásának egyszerű módja. Általános alakja:
| + | |
− | <python>
| + | |
− | [expression for expr in sequence1
| + | |
− | if condition1
| + | |
− | for expr2 in sequence2
| + | |
− | if condition2
| + | |
− | ...
| + | |
− | for exprN in sequenceN
| + | |
− | if conditionN]
| + | |
− | </python>
| + | |
− | Kis programrészek helyettesíthetők vele. Például '''''soroljuk fel az 1890 és 1915 közé eső szökőéveket!'''''
| + | |
− | | + | |
− | <python>
| + | |
− | 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]
| + | |
− | </python>
| + | |
− | Lépésenként egyre összetettebb listaértelmezéssel állítsuk elő ugyanezt:
| + | |
− | <python>
| + | |
− | >>> 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]
| + | |
− | </python>
| + | |
− | | + | |
− | Egy egyszerű algoritmus egy különböző elemekből álló lista összes permutációja listájának előállítására:
| + | |
− | | + | |
− | <python>
| + | |
− | 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 [[]]
| + | |
− | </python>
| + | |
− | | + | |
− | Például:
| + | |
− | <python>
| + | |
− | >>> perm([])
| + | |
− | [[]]
| + | |
− | >>> perm([1, 2, 3])
| + | |
− | [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
| + | |
− | </python>
| + | |
− | | + | |
− | | + | |
− | '''*''' 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:
| + | |
− | | + | |
− | <python>
| + | |
− | 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
| + | |
− | </python>
| + | |
− | | + | |
− | === 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?
| + | |
− | | + | |
− | | + | |
− | | + | |
− | === Operátorok precedenciája ===
| + | |
− | | + | |
− | Az operátorok között, mint a matematikában itt is, van precedencia sorrend:
| + | |
− | | + | |
− | {| class="wikitable" style="text-align: center; color: green;"
| + | |
− | ! 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
| + | |
− | |-
| + | |
− | |<code>+, -</code>
| + | |
− | |Addition and subtraction
| + | |
− | |-
| + | |
− | |*, //, /, %
| + | |
− | |Multiplication, division, remainder
| + | |
− | |-
| + | |
− | |<code>+x, -x, ~x</code>
| + | |
− | |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 ===
| + | |
| | | |
| <python> | | <python> |
− | >>> x = int(raw_input("Adj meg egy egész számot: ")) | + | >>> def kulso(x): |
− | Adj meg egy egész számot: 42
| + | ... def belso(): |
− | >>> if x < 0:
| + | ... print x |
− | ... print "ez negatív" | + | ... return belso |
− | ... elif x == 0:
| + | |
− | ... print "ez nulla" | + | |
− | ... elif x == 1:
| + | |
− | ... print "ez egy" | + | |
− | ... else:
| + | |
− | ... print "ez sok"
| + | |
| ... | | ... |
− | ez sok
| + | >>> f1 = kulso(3) |
| + | >>> f2 = kulso(5) |
| + | >>> |
| + | >>> f1() |
| + | 3 |
| + | >>> f2() |
| + | 5 |
| </python> | | </python> |
| | | |
− | Az elif-ek száma tetszőleges, és ezzel elkerülhető a sok behúzás.
| + | ==== Dekorálunk ==== |
| | | |
− | A következő kóddal tesztelhető, hogy milyen kifejezéseket tekint a python igaznak: | + | A külső függvény az argumentumában átadott függvény eredményét duplázza, és ezt a duplázó függvényt adja vissza. Ezzel '''dekorálunk''' két különböző függvényt! |
− | <python>
| + | |
− | 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"
| + | |
− | </python>
| + | |
− | | + | |
− | | + | |
− | === for, break, else, continue ===
| + | |
| | | |
| <python> | | <python> |
− | >>> long_words = [u"Antidisestablishmentarianism", | + | >>> def kulso(fn): |
− | u"Donaudampfschiffahrtselektrizitätenhauptbetriebswerkbauunterbeamtengesellschaft",
| + | ... def belso(*args): |
− | u"bejelentkezésszabályozási", u"fosszilisdinoszauruszhányásvilágranglista-megdöntés",
| + | ... print "belül vagyunk" |
− | u"folyamatellenőrzésiügyosztályvezetőhelyettesképesítésvizsgálat-szervezéseitekkel"]
| + | ... return 2*fn(*args) |
− | >>> for i in long_words:
| + | ... return belso |
− | ... print i, len(i) | + | |
| ... | | ... |
− | Antidisestablishmentarianism 28
| + | >>> dekoralt = kulso(fv) |
− | Donaudampfschiffahrtselektrizitätenhauptbetriebswerkbauunterbeamtengesellschaft 79
| + | >>> dekoralt(5) |
− | bejelentkezésszabályozási 25
| + | belül vagyunk |
− | fosszilisdinoszauruszhányásvilágranglista-megdöntés 51
| + | 10 |
− | folyamatellenőrzésiügyosztályvezetőhelyettesképesítésvizsgálat-szervezéseitekkel 80
| + | >>> def fadd(a, b): |
− | </python>
| + | ... return a + b |
− | | + | |
− | '''''Döntsük el 10-ig minden egészről, hogy prím vagy összetett szám!'''''
| + | |
− | <python>
| + | |
− | >>> 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
| + | >>> dekoralt = kulso(fadd) |
− | 3 prím
| + | >>> dekoralt(4, 5) |
− | 4 = 2 * 2 | + | belül vagyunk |
− | 5 prím | + | 18 |
− | 6 = 2 * 3
| + | |
− | 7 prím
| + | |
− | 8 = 2 * 4
| + | |
− | 9 = 3 * 3
| + | |
| </python> | | </python> |
− | 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!'''''
| + | A <code>fv = kulso(fv)</code> rövidítése a <code>@kulso</code> a fv függvénydefiníció elé írásával: |
− | <python> | + | |
− | >>> 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 *
| + | |
− | </python> | + | |
− | | + | |
− | === while, braek, else ===
| + | |
| | | |
− | '''''Írjuk ki az 1000 alatti Fibonacci-számokat:'''''
| |
| <python> | | <python> |
− | >>> n = 1000 | + | >>> @kulso |
− | >>> a, b = 0, 1
| + | ... def fmul(a, b): |
− | >>> while a < n:
| + | ... return a * b |
− | ... 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
| + | >>> fmul(3, 5) |
| + | belül vagyunk |
| + | 30 |
| </python> | | </python> |
| | | |
− | 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ő:
| + | Dekorátor lehet olyan osztály is, mely '''meghívható''', azaz amelyben létezik <code>__call__</code> függvény: |
− | <python> | + | |
− | while True:
| + | |
− | utasítások
| + | |
− | if kilépési_feltétel:
| + | |
− | break
| + | |
− | (utasítások)
| + | |
− | </python> | + | |
− | | + | |
− | === pass ===
| + | |
− | | + | |
− | Nem csinál semmit, ami sokszor nagyon jól jöhet:
| + | |
| | | |
| <python> | | <python> |
− | while True:
| + | >>> class Dekorator(object): |
− | pass # Várunk egy billentyűzet interruptot (Ctrl+C)
| + | ... def __init__(self, f): |
− | </python>
| + | ... print "Dekorátor konstruktor" |
− | | + | ... print "meghívjuk a fv-t:", f() |
− | | + | ... def __call__(self): |
− | <python>
| + | ... print "Dekorátor meghívása" |
− | def func(*args):
| + | |
− | pass # megírandó
| + | |
− | </python>
| + | |
− | | + | |
− | | + | |
− | == Függvények ==
| + | |
− | | + | |
− | Opcionálisan megadható '''argumentumok alapértelmezett értékkel''':
| + | |
− | <python>
| + | |
− | 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
| + | |
− | </python>
| + | |
− | | + | |
− | Néhány lehetséges meghívása:
| + | |
− | <python>
| + | |
− | ask_ok("Is it OK? ")
| + | |
− | ask_ok("May I delete your files? ", 0)
| + | |
− | ask_ok("Törölhetem a wincsesztert? ", 1, "Igen vagy nem? ")
| + | |
− | </python>
| + | |
− | | + | |
− | 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:
| + | |
− | <python>
| + | |
− | def f(a, L=[]):
| + | |
− | L.append(a)
| + | |
− | return L
| + | |
− | | + | |
− | print f(1)
| + | |
− | print f(2)
| + | |
− | print f(5)
| + | |
− | </python>
| + | |
− | A futás eredménye:
| + | |
− | <python>
| + | |
− | [1]
| + | |
− | [1, 2]
| + | |
− | [1, 2, 5]
| + | |
− | </python>
| + | |
− | | + | |
− | E mellékhatás elkerülésére [] helyett None-t használjunk!
| + | |
− | <python>
| + | |
− | def f(a, L=None):
| + | |
− | if L is None:
| + | |
− | L = []
| + | |
− | L.append(a)
| + | |
− | return L
| + | |
− | </python>
| + | |
− | | + | |
− | Az argumentumok megadhatók ''kulcsszó'' = ''érték'' alakban a kötelező argumentumok esetén is. Így az argumentumok sorrendje is megváltoztatható,
| + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | == Adatstruktúrák ==
| + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | | + | |
− | <!--
| + | |
− | | + | |
− | <python>
| + | |
− | </python>
| + | |
− | | + | |
− | | + | |
− | = A Python eljárásközpontú (procedurális) programozása =
| + | |
− | | + | |
− | == Adattípusok ==
| + | |
− | | + | |
− | | + | |
− | == Gyűjteményes adattípusok ==
| + | |
− | | + | |
− | === Sorozatszerű típusok: str, list, tuple ===
| + | |
− | | + | |
− | Tuladonságaik: bejárhatók, in, len(), []
| + | |
− | | + | |
− | '''Sorozat (tuple)''' változtathatatlan (immutable), mint a karakterlánc, műveletei:
| + | |
− | szeletelés [], összefűzés (+), szorzás (*), összehasonlítás, tagsági viszony (in, not in)
| + | |
− | <python>
| + | |
− | >>> t = ()
| + | |
− | >>> t
| + | |
− | ()
| + | |
− | >>> t = 1, 5, 5, 5, 3 # itt elhagyható a zárójel
| + | |
− | >>> t
| + | |
− | (1, 5, 5, 5, 3)
| + | |
− | >>> t[1]
| + | |
− | 5
| + | |
− | >>> t.index(3)
| + | |
− | 4
| + | |
− | >>> t.count(5)
| + | |
− | 3
| + | |
− | </python>
| + | |
− | | + | |
− | | + | |
− | '''lista''' - változtatható (mutable)
| + | |
− | [http://docs.python.org/release/2.5.2/lib/typesseq-mutable.html]
| + | |
− | <python>
| + | |
− | >>> l[1:4:2] = [7, 8]
| + | |
− | >>> l
| + | |
− | [1, 7, 3, 8, 5]
| + | |
− | >>> l.remove(7); l
| + | |
− | [1, 3, 8, 5]
| + | |
− | >>> l.reverse(); l
| + | |
− | [5, 8, 3, 1]
| + | |
− | >>> l.append(99); l
| + | |
− | [5, 8, 3, 1, 99]
| + | |
− | >>> l += [55, 66]
| + | |
− | >>> l
| + | |
− | [5, 8, 3, 1, 99, 55, 66]
| + | |
− | >>> l.pop()
| + | |
− | 66
| + | |
− | >>> l
| + | |
− | [5, 8, 3, 1, 99, 55]
| + | |
− | </python>
| + | |
− | | + | |
− | === Halmaztípusok: halmaz (set) ===
| + | |
− | | + | |
− | Lásd
| + | |
− | [http://docs.python.org/release/2.5.2/lib/types-set.html]
| + | |
− | <python>
| + | |
− | >>> s = set([5,6,7,8,6])
| + | |
− | >>> s
| + | |
− | set([8, 5, 6, 7])
| + | |
− | >>> s2 = set()
| + | |
− | >>> s2
| + | |
− | set([])
| + | |
− | >>> s2 = s.copy()
| + | |
− | >>> s2
| + | |
− | set([8, 5, 6, 7])
| + | |
− | >>> s2.add(6)
| + | |
− | >>> s2.add(11)
| + | |
− | >>> s2
| + | |
− | set([8, 11, 5, 6, 7])
| + | |
− | >>> s2.difference(s)
| + | |
− | set([11])
| + | |
− | >>> s2.discard(11)
| + | |
− | >>> s2.difference(s)
| + | |
− | set([])
| + | |
− | >>> s2.intersection(s)
| + | |
− | set([8, 5, 6, 7])
| + | |
− | >>> s2.update([5,4,3])
| + | |
− | >>> s2
| + | |
− | set([3, 4, 5, 6, 7, 8])
| + | |
− | >>> s2.discard(2)
| + | |
− | >>> s2
| + | |
− | set([3, 4, 5, 6, 7, 8])
| + | |
− | >>> s2.remove(3)
| + | |
− | >>> s2
| + | |
− | set([4, 5, 6, 7, 8])
| + | |
− | >>> s2.remove(3)
| + | |
− | Traceback (most recent call last):
| + | |
− | File "<stdin>", line 1, in <module>
| + | |
− | KeyError: 3
| + | |
− | >>> s
| + | |
− | set([8, 5, 6, 7])
| + | |
− | >>> s.union(set([56,5]))
| + | |
− | set([56, 5, 6, 7, 8])
| + | |
− | >>> s
| + | |
− | set([8, 5, 6, 7])
| + | |
− | >>> s2
| + | |
− | set([4, 5, 6, 7, 8])
| + | |
− | >>> s.clear()
| + | |
− | >>> s
| + | |
− | set([])
| + | |
− | </python>
| + | |
− | | + | |
− | === Megfeleltetési típusok: szótár (dict) ===
| + | |
− | | + | |
− | Lásd
| + | |
− | [http://docs.python.org/release/2.5.2/lib/typesmapping.html]
| + | |
− | <python>
| + | |
− | >>> d = dict()
| + | |
− | >>> d
| + | |
− | {}
| + | |
− | >>> d = {}
| + | |
− | >>> d
| + | |
− | {}
| + | |
− | >>> d = {'fn':'Marci', 'ln':'Pala', 2:89}
| + | |
− | >>> d
| + | |
− | {'ln': 'Pala', 2: 89, 'fn': 'Marci'}
| + | |
− | >>> d[2]
| + | |
− | 89
| + | |
− | >>> d['ln']
| + | |
− | 'Pala'
| + | |
− | >>> d2 = d.copy()
| + | |
− | >>> d2
| + | |
− | {'ln': 'Pala', 2: 89, 'fn': 'Marci'}
| + | |
− | >>> d2[2] = 8
| + | |
− | >>> d2
| + | |
− | {'ln': 'Pala', 2: 8, 'fn': 'Marci'}
| + | |
− | >>> d
| + | |
− | {'ln': 'Pala', 2: 89, 'fn': 'Marci'}
| + | |
− | >>> d.update([("t",3),('b',6)])
| + | |
− | >>> d
| + | |
− | {'ln': 'Pala', 2: 89, 'b': 6, 't': 3, 'fn': 'Marci'}
| + | |
− | >>> d2
| + | |
− | {'ln': 'Pala', 2: 8, 'fn': 'Marci'}
| + | |
− | >>> d.values()
| + | |
− | ['Pala', 89, 6, 3, 'Marci']
| + | |
− | >>> d.pop('b')
| + | |
− | 6
| + | |
− | >>> d
| + | |
− | {'ln': 'Pala', 2: 89, 't': 3, 'fn': 'Marci'}
| + | |
− | >>> d.keys()
| + | |
− | ['ln', 2, 't', 'fn']
| + | |
− | >>> d.items()
| + | |
− | [('ln', 'Pala'), (2, 89), ('t', 3), ('fn', 'Marci')]
| + | |
− | >>> d.clear()
| + | |
− | >>> d
| + | |
− | {}
| + | |
− | >>> len(d)
| + | |
− | 0
| + | |
− | >>> d2
| + | |
− | {'ln': 'Pala', 2: 8, 'fn': 'Marci'}
| + | |
− | </python>
| + | |
− | | + | |
− | === Listaértelmezések (list comprehension) ===
| + | |
− | | + | |
− | | + | |
− | | + | |
− | === Gyűjtemények másolása (sekély és mély másolás) ===
| + | |
− | | + | |
− | == Műveletek, operátorok ==
| + | |
− | | + | |
− | | + | |
− | == Vezérlési szerkezetek ==
| + | |
− | *Elágazás
| + | |
− | **if (elif, else)
| + | |
− | *Ciklusok
| + | |
− | **while (else)
| + | |
− | **for (else)
| + | |
− | **break, continue
| + | |
− | | + | |
− | * Lényeges, hogy a while és for ciklusokhoz itt hozzárendelhető else ág. Ezek használatát mutatja be az alábbi két példa:
| + | |
− | <python>
| + | |
− | while condition:
| + | |
− | handle_true() | + | |
− | else:
| + | |
− | # condition is false now, handle and go on with the rest of the program
| + | |
− | handle_false()
| + | |
− | </python>
| + | |
− | | + | |
− | <python>
| + | |
− | for value in values:
| + | |
− | if value == 5:
| + | |
− | print "Found it!"
| + | |
− | break
| + | |
− | else:
| + | |
− | print "Nowhere to be found. :-("
| + | |
− | </python>
| + | |
− | | + | |
− | | + | |
− | == Függvények ==
| + | |
− | | + | |
− | * Python ban is van lehetőség függvények definiálására és hívására.
| + | |
− | * Függvényeknek itt is lehetnek paraméterei
| + | |
− | * Ha rögzítjük a paraméterszámot, akkor ennek megfelelően kell hívnunk a függvényt.
| + | |
− | * Lehetséges előre beállított paraméterekkel való hívás is. Ebben az esetben, az egyértelműség miatt a definiáláskor hátul adunk meg minen előre is definiált paramétert.
| + | |
− | * Példa
| + | |
− | <python>
| + | |
− | def a_d_test(fv, vert = 1): | + | |
− | return fv * vert
| + | |
− |
| + | |
− | a_d_test(5,2)
| + | |
− | 10
| + | |
− | a_d_test(5)
| + | |
− | 5
| + | |
− | </python>
| + | |
− | * Pararméterek nevének különákülön való megadásával is átadhatjuk azok értékeit híváskor.
| + | |
− | <python>
| + | |
− | a_d_test(vert=2, fv=2)
| + | |
− | </python>
| + | |
− | * Speciálisan megadhatunk tetszőleges paraméterszámú függvényeket.
| + | |
− | <python>
| + | |
− | def as_many(*args):
| + | |
− | for i in args:
| + | |
− | print i,
| + | |
− |
| + | |
− | as_many('trali', 'fari')
| + | |
− | trali fari
| + | |
− | </python>
| + | |
− | | + | |
− | == Láthatóságról ==
| + | |
− | * A kód itt is blokkokba rendeződik és egy változó befelé látszik, kifelé nem.
| + | |
− | * A belső deklaráció "leárnyékol".
| + | |
− | * Ez a küd tehát hibás, mert a b=a utasítás blokkján belül az a=6 utasítással létrehozzuk az a lokális változót. Emiatt leárnyékoljuk a külső a változót, és a b=a utasításnál így hibát kapunk.
| + | |
− | <python>
| + | |
− | a=7
| + | |
− | def sz3():
| + | |
− | b=a
| + | |
− | a=6
| + | |
− | return b
| + | |
− |
| + | |
− | Traceback (click to the left of this block for traceback)
| + | |
− | ...
| + | |
− | UnboundLocalError: local variable 'a' referenced before assignment
| + | |
− | </python>
| + | |
− | | + | |
− | == Kivételkezelés ==
| + | |
− | * Lehetőségünk van kivételek, hibák kezelésére.
| + | |
− | * '''try''' és '''except''' blokkok használatával kezelhetjük a hibát adható részeit a kódnak.
| + | |
− | * '''A try blokkon belül megpróbáljuk végrehajtani az ott felsorolt utasításokat.'''
| + | |
− | * '''Ha ez nem sikerül, akkor a felmerülő hibát az except blokkal "kapjuk el".'''
| + | |
− | * Példa, alább magyarázattal:
| + | |
− | <python>
| + | |
− | while True:
| + | |
− | ... try:
| + | |
− | ... x = int(raw_input("Please enter a number: ")) | + | |
− | ... break
| + | |
− | ... except ValueError:
| + | |
− | ... print "Oops! That was no valid number. Try again..." | + | |
− | </python>
| + | |
− | * A while True egy végtelen ciklus, mellyel break utasítással léphetünk ki. A break utasítás csak akkor fut le, ha előtte a felhasználótól hibátlanul bekértünk egy számot. Ha ez nem sikerült, akkor a try blokkból kilépünk a break utasíts előtt és ugrunk az except részre. Mivel mindez egy végtelen while ciklusban van, ezért ezt addig filytatjuk, amíg helyes bemenetet nem kapunk.
| + | |
− | * '''Tehát megpróbáljuk végrehajtani a try blokkon belüli utasításokat, de amint hibát észlelünk, kilépünk a try blokkból.'''
| + | |
− | * A hibát az except blokkal kezeljük.
| + | |
− | * Az except után megadhatjuk a hiba típusát, így a különböző hibákat különbözőféleképp kezelhetjük:
| + | |
− | <python>
| + | |
− | try:
| + | |
− | z = x/y
| + | |
− | except ZeroDivisionError, e:
| + | |
− | z = e # representation: "<exceptions.ZeroDivisionError instance at 0x817426c>"
| + | |
− | print z
| + | |
− | </python>
| + | |
− | == Bemenet, kimenet ==
| + | |
− | | + | |
− | Lsd. gyakorlaton
| + | |
− | | + | |
− | = A Python objektumorientált programozása =
| + | |
− | * Ez a wiki szintén jól használható: http://en.wikibooks.org/wiki/Python_Programming/Classes
| + | |
− | == Osztályok, objektumok ==
| + | |
− | * Az osztályok egységbe zárnak és a elrejtik a felesleges információt.
| + | |
− | * Egy lehetséges nézőpont: a kód egy részét (mind tárolókat, mind a függvényeket nézve) összefogjuk, és a kifelé felesleges műveleteket és változókat elrejtjük.
| + | |
− | * Egy objektum egy osztály konkrét megvalósítása. Egy osztályban definiáljuk az objektum jellemzőit.
| + | |
− | * Egy osztály metódusokból és változókból áll.
| + | |
− | * Egy másik nézőpont: Az osztályon belül változókkal hozunk létre adattárolókat. Metódusokkal ezeket az adattárolókat érjük el kívülről.
| + | |
− | * Példa osztály definiálásra pythonban:
| + | |
− | <python>
| + | |
− | class Osztaly:
| + | |
− | "Ez az uj csodafegyver" | + | |
− | pass
| + | |
− | </python>
| + | |
− | A feni osztály még csak egy üres osztály. Ennek az egyszerű osztálynak egy objektum megvalósítása:
| + | |
− | <python>
| + | |
− | >>> o=Osztaly()
| + | |
− | </python>
| + | |
− | * Másszóval az o objektum az Osztaly osztály egy '''példánya'''.
| + | |
− | A következő kódrészlet metódus definiálására példa:
| + | |
− | <python>
| + | |
− | class Osztaly:
| + | |
− | ... def make_sandwich(self):
| + | |
− | ... self.sandwich=6
| + | |
− | >>> x=Osztaly()
| + | |
− | >>> x.make_sandwich()
| + | |
− | </python>
| + | |
− | * Ebben a példában az Osztaly osztályban definiáljuk a make_sandwitch() metódust. Az x objektum példányoztatása után az x objektumhoz tartozó make_sandwich() metódust hívjuk meg az utolsó sorban.
| + | |
− | * Így kap értelmet a 'self' kifejezés. A metódusoknál az osztálydefinícióban jeleznünk kell, hogy az adott objektumon dolgozunk, és annak változóival hajtunk végre műveletet.
| + | |
− | * Emiatt minden metódus első paramétere a 'self', ami mindig az osztály egy példányára ( megvalósított objektum) hivatkozik.
| + | |
− | * A self.sandwich emiatt az adott objektum változója lesz.
| + | |
− | * Ha tehát meghívjuk a make_sandwich() metódust, akkor az az adott objektumon belül létrehozza a sandwich változót kezdeti 6 értékkel.
| + | |
− | == Láthatóság ==
| + | |
− | * Említettük, hogy az osztályok egységbe zárnak és elrejtik a felesleges információt. Az "elrejtés" azt jelenti, hogy valamilyen módon korlátoznunk kell az osztály változóira és metódusaira (továbbiakban elemek) vonatkozó hozzáférést.
| + | |
− | * Az osztály egy eleme lehet: public, protected, private:
| + | |
− | ** public: publikus elem hozzáférhető az objektumon kívülről is.
| + | |
− | ** private: privát elem csak az osztályon (objektumon) belül érhető el.
| + | |
− | ** protected: alosztályok ( lsd. később) és az eredeti osztály számára elérhető elem.
| + | |
− | * Pythonban '''minden változó és metódus publikus'''
| + | |
− | * A fenti szabály ellenére érdemes bizonyos dolgokat privát módon kezelni a kódban (annak ellenére, hogy lehetőségünk lenne őket kívülről elérni). Emiatt a változók és metódusok elnevezésében a következő konvenciót használjuk:
| + | |
− | ** _ha_muszaj_elerem
| + | |
− | ** __soha_nem_irom_felul__
| + | |
− | * Változók:
| + | |
− | ** osztály szintű: ha megváltoztatjuk az értékét az osztályon belül, akkor minden egyes objektumban megváltozik az értéke.
| + | |
− | ** objektum szintű: adott objektumhoz tartozó változó
| + | |
− | * Példa változókra:
| + | |
− | <python>
| + | |
− | class A:
| + | |
− | ... u=8
| + | |
− | ... def make_v(self):
| + | |
− | ... self.v=6
| + | |
− | >>> x=A()
| + | |
− | >>> y=A()
| + | |
− | >>> y.make_v()
| + | |
− | </python>
| + | |
− | * A fenti példában az x és y objektumok az A osztály példányai. Mindkettőben megjelenik az osztály szintű u változó. Az y objektum make_v() metódusánk meghívása után (csak!) az y objektumban megjelenik a v változó.
| + | |
− | | + | |
− | == Konstruktor és destruktor ==
| + | |
− | | + | |
− | * Azt az adott osztályhoz tartozó szubrutint, melynek feladata az osztály egy konkrét objektumának megvalósítása, konstruktornak hívjuk.
| + | |
− | * Ehhez hasonló az objektum törlésekor hívódó destruktor.
| + | |
− | * Pythonban külön nincs lehetőség ezek felüldefiniálására. A Python szokásos értelemben nem használ konstruktorokat és destruktorokat.
| + | |
− | * Azonban létezik olyan speciális metódus, mely az objektum létrehozása után közvetlenül lefut, ez az __init__():
| + | |
− | * Az inithez hasonló a __del__().
| + | |
− | * Példa az __init__()-re:
| + | |
− | <python>
| + | |
− | | + | |
− | >>> class Test:
| + | |
− | ... def __init__(self):
| + | |
− | ...
| + | |
− | ... print "Mostmar elhiszed?" | + | |
− | ...
| + | |
− | >>> x=Test()
| + | |
− | Mostmar elhiszed?
| + | |
− | </python>
| + | |
− | * A Test osztály megvalósítása az x objektum. Az x objektum létrejöttekor az __init__() azonnal lefut, emiatt jelenik meg rögtön a kimeneten a "Mostmar elhiszed?" felirat.
| + | |
− | == Speciális metódusok pythonban ==
| + | |
− | | + | |
− | * az __init__() és __del__() metódusok mellett további speciális metódusok is elemei a nyelvnek.
| + | |
− | * Ilyen például a __repr__() és az __str__(), melyek az adott osztály (objektum) leírását adják.
| + | |
− | * Alapelv, hogy az __str__() legyen egyszerű, míg a __repr__() legyen egyértelmű.
| + | |
− | * Példa:
| + | |
− | <python>
| + | |
− | >>> class A:
| + | |
− | ... x=5
| + | |
| ... | | ... |
− | >>> a=A() | + | >>> @Dekorator |
− | >>> a
| + | ... def fn(): |
− | <__main__.A instance at 0x7f1563927b90>
| + | ... print "az fn meghívása" |
− | >>> class B:
| + | |
− | ... x=5
| + | |
− | ... def __repr__(self): | + | |
− | ... return "ez egy okos osztaly" | + | |
| ... | | ... |
− | >>> b=B() | + | Dekorátor konstruktor |
− | >>> b
| + | meghívjuk a fv-t: az fn meghívása |
− | ez egy okos osztaly
| + | None |
| + | >>> fn() |
| + | Dekorátor meghívása |
| </python> | | </python> |
− | * A fenti példákon túl még több speciális metódus létezik. Lényegesek azon metódusok, melyekkel objektumokhoz tartozó operátorokat definiálhatunk.
| |
− | * Mindezekről részletesen a [http://wiki.math.bme.hu/view/Informatika2-2013/Gyakorlat11 gyakorlaton esett szó].
| |
− | * Egy példa az előadás anyagához:
| |
− |
| |
− | <python>
| |
− | class Word(str):
| |
− | '''Class for words, defining comparison based on word length.'''
| |
− | def __new__(cls, word):
| |
− | return str.__new__(cls, word)
| |
− | def __gt__(self, other):
| |
− | return len(self) > len(other)
| |
− | def __lt__(self, other):
| |
− | return len(self) < len(other)
| |
− | def __ge__(self, other):
| |
− | return len(self) >= len(other)
| |
− | def __le__(self, other):
| |
− | return len(self) <= len(other)
| |
− | </python>
| |
− | * A fenti példával stringeket hasonlíthatunk össze hosszuk alapján.
| |
− | == Öröklődés, leszármaztatás ==
| |
− | * Öröklődés (leszármaztatás) esetén egy osztályból származtatunk le egy másik osztályt. Az ősosztály leszármazottja (alosztály) örökli az ősosztály tulajdonságait.
| |
− | * Itt kap értelmet a "private" és "public" típusok mellett a "protected" típus. Minden ami publikus vagy protected az ősosztályban, az szintén eleme lesz a származtatott osztálynak. Ne feledjük, hogy pythonban minden változó és metódus publikus.
| |
− | * A fentiek már majdnem egyértelmű szabályokat adnak. Kérdés még, hogy abban az esetben, ha azonos metódusokat definiálunk az ős és az alosztályban, akkor melyik lesz érvényes az alosztályban?
| |
− | * Pythonban minden metódus virtuális. Ez azt jelenti, hogy az előző kettős definiálás esetén az alosztály definíciója lesz érvényes, tehát '''felüldefiniáljuk''' az eredeti metódust.
| |
− | Példák:
| |
− | <python>
| |
− | >>> class A:
| |
− | ... x=8
| |
− | ... def __init__(self):
| |
− | ... self.u=6
| |
− | >>> class B(A):
| |
− | ... y=5
| |
− | ... def __init__(self):
| |
− | ... self.v=7
| |
− | >>> a=A()
| |
− | >>> b=B()
| |
− | </python>
| |
− | * A fenti példában az a onjektum x és u, mg a b objektum x,y és v változókat fog magába foglalni.
| |
− | * Előfordulhat, hogy az ősosztály egy metódusára szeretnénk hivatkozni az alosztály egy metódusában. Ezt a következőképp tehetjük meg:
| |
− | <python>
| |
− | class A(object):
| |
− | def proba(self):
| |
− | print "A osztaly"
| |
− |
| |
− | class B(A):
| |
− | def proba2(self):
| |
− | super(B, self).proba()
| |
− | print "B osztaly"
| |
− | </python>
| |
− | * A fenti példában a proba2() metódus meghívja az A osztályban definiált proba() metódust.
| |
− |
| |
− | -->
| |
− |
| |
− |
| |
− |
| |
− |
| |
− | == a pythononline.org tesztelése ==
| |
− |
| |
− | Lássuk, hogy néz ki: példa a sekély másolásra:
| |
− |
| |
− |
| |
− | Idáig tart a beágyazás!
| |
− |
| |
− | <wikiframe width="800" height="500" frameborder="0" src="http://pythontutor.com/iframe-embed.html#code=def+lnko(a,+b)%3A%0A++++a,+b+%3D+abs(a),+abs(b)%0A++++while+a+!%3D+0%3A%0A++++++++a,+b+%3D+b+%25+a,+a%0A++++return+b%0A%0Aprint+lnko(-36,+8)%0Aprint+lnko(128,+9)&cumulative=false&heapPrimitives=false&drawParentPointers=false&textReferences=false&showOnlyOutputs=false&py=2&curInstr=0&codeDivWidth=350&codeDivHeight=400" />
| |
− |
| |
− | Idáig meg a másik, minden átszerkesztés nélkül.
| |
Minden új függvény fölépíti saját névterét, egy szótár formájában. Íme a globális és egy lokális névtér:
Ha egy név lokálisan nem lett létrehozva, a tartalmazó névterekben keresi egyre kijjebb haladva (itt az x nem lett lokálisan létrehozva, de elérhető):
És mi történik, ha a 3. és 4. sort fölcseréljük?
A névtér törlődik a függvény lefutása után, magasabb szinten az alacsonyabb szintű névterek nem érhetők el:
A külső függvény az argumentumában átadott függvény eredményét duplázza, és ezt a duplázó függvényt adja vissza. Ezzel dekorálunk két különböző függvényt!