Loeng 8: Sisseehitatud funktsioonide ülevaade, funktsiooni sulund, dekoraator ja operaator @, lausend assert, moodul ja faililaiend .py, programmi käivitamine käsurealt konsoolis, integreeritud arenduskeskkonna tutvustus ja kasutamine, kursusetöö juhend ja näidis¶
Koodinäited¶
1 Sisseehitatud funktsioonide ülevaade (Built-in functions)¶
1.1 Funktsioon¶
Funktsioon saab olla
- enda kirjutatud,
- standarteegis defineeritud või
- kolmandate osapoolete teekides defineeritud
taaskasutatav koodiblokk, vt. Joonis 1. Funktsioonid saavad vajadusel vastu võtta argumente ja väljastada tulemusi või teostada tegevusi. Funktsioonide taaskasutatavus võimaldab programeerida efektiivsemalt aidates organiseerida ja korrastada koodi.
Pythoni standardteek sisaldab paljusid funktsioone mida me pole veel sellel kursusel maininud. Osadega nendest oleme juba tutvunud. Joonis 1 kujutab Pythoni programmi ja selle osasid.
| Joonis 1. Pythoni programm ja selle osad. Pythoni installatsiooniga tuleb kaasa staandardteek ja interpretaator. |
Meeldetuletus: Siiamaani oleme tutvunud muuseas sellega kuidas defineerida enda kirjutatud funktsioone, anonüümseid funktsioone ja generaatoreid. Me teame kuidas kasutada lausendeid def ja lambda funktsiooni defineerimiseks ning lausendeid return ja yield tulemuste väljastamiseks. Lisaks oleme kasutanud erinevaid tüüpi argumente (positsionaalsed, vaikeväärtusega, args- ja kwargs-tüüpi argumendid).
1.2 Valik sissehitatud funktsioone¶
Järgnev on lühike ülevaade olulisematest funktsioonidest. Osad funktsioonidest on meile juba tuttavad.
Valik sisseehitatud funktsioone ja nende väljakutse süntaks:
range(stop)
range(start, stop[, step])
input([prompt])
len(s)
max(iterable[, key])
max(arg1, arg2, *args[, key])
min ...
id(object)
hash(object)
int(x, base=10)
float([x])
complex([real[, imag]])
str(object='')
list([iterable])
tuple([iterable])
dict(**kwarg)
dict(mapping, **kwarg)
dict(iterable, **kwarg)
set([iterable])
frozenset([iterable])
bool([x])
divmod(a, b)
pow(x, y[, z])
abs(x)
round(number[, ndigits])
chr(i)
bin(x)
ord(c)
hex(x)
all(iterable)
any(iterable)
reversed(seq)
sorted(iterable[, key[, reverse]]])
map(func, iterable, ...)
filter(func, iterable)
sum(iterable[, start])
zip([iterable, ...])
enumerate(sequence[, start=0])}
dir([object])
locals()
globals()
eval(expression[, globals[, locals]])
exec(source[, globals[, locals[, closure]]])
repr(object)
isinstance(object, classinfo)
issubclass(class, classinfo)
callable(object)
iter(object[, sentinel])
Kõigi sisseehitatud objektide, millede seas on ka funktsioonid, järgivaatamiseks kasuta funktsiooni dir:
import builtins # Lausendist importi räägime tulevastes loengutes.
#dir(builtins) # Vt. iseseisvalt
1.3 Sisseehitatud funktsioonide kasutamine¶
1.3.1 Funktsioon round¶
Kasutame arvude ümardamiseks. Funktsiooni dokumentatsioon:
round?
Signature: round(number, ndigits=None) Docstring: Round a number to a given precision in decimal digits. The return value is an integer if ndigits is omitted or None. Otherwise the return value has the same type as the number. ndigits may be negative. Type: builtin_function_or_method
NB! Viiega lõppevaid murdarve ümardame lähima paarisarvu suunas või lähima küsitud paarisarvulise komakohani, mitte suurema arvu suunas nagu õpetati enamustes põhikoolides.
Funktsiooni kasutamise süntaks on järgmine:
round(4.5) # Tutvu iseseisvalt ja vt alla: Nn. "odd-even rounding rule".
4
print(round(0.125, 2)) # Ümarda kahe komakohani kasutades odd-even rounding rule'i.
print(round(0.005, 2)) # Ümarda kahe komakohani.
0.12 0.01
Märkus: Uurides ülemise raku rida 2 tundub, et Python rikub enda reegleid mille kohaselt $0.005 \approx 0.00 \equiv 0$ mitte $0.005 \approx 0.01$ nagu just juhtus. Kuidas seda seletada? See juhtus kuna ujuvkomakohaga arvu (float) ei saa arvutis üldjuhul täpselt esitada. Loe lisaks: https://docs.python.org/3.14/library/functions.html#round
round(2.87678, 3) # Ümarda kolmanda komakohani.
2.877
1.3.1.1 Ümardamisest¶
Pythoni reegli mis puudutab arve mis lõppevad viiega kus me ümardame lähime paarisarvuni (odd-even rounding rule) põhjendus. Funktsioon round rakendamine arvudele 0.5, 1.5, 2.5 jne.:
print('Arv --> Ümardatud arv')
lst0, lst = [], []
for i in range(10):
arv = i + 0.5
round_arv = round(arv) # Pythoni funktsioon round.
print(arv, ' --> ', round_arv)
lst0.append(arv)
lst.append(round_arv)
print(f'Algandmete keskmine: {sum(lst0) / 10}')
print('Ümardatud arvude keskmine:', sum(lst) / 10)
Arv --> Ümardatud arv 0.5 --> 0 1.5 --> 2 2.5 --> 2 3.5 --> 4 4.5 --> 4 5.5 --> 6 6.5 --> 6 7.5 --> 8 8.5 --> 8 9.5 --> 10 Algandmete keskmine: 5.0 Ümardatud arvude keskmine: 5.0
Võrdluseks: Kui kasutada põhikoolis õpetatud valet reeglit kus ümardatakse alati ülesse kui pole muid juhendeid antud, siis saame:
import math # Lausendist importi räägime tulevastes loengutes.
print('Arv --> Ümardatud arv')
lst0, lst = [], []
for i in range(10):
arv = i + 0.5
round_arv = math.ceil(arv) # Ümardame ülesse.
print(arv, ' --> ', round_arv)
lst0.append(arv)
lst.append(round_arv)
print(f'Algandmete keskmine: {sum(lst0) / 10}')
print('Ümardatud arvude keskmine:', sum(lst) / 10)
Arv --> Ümardatud arv 0.5 --> 1 1.5 --> 2 2.5 --> 3 3.5 --> 4 4.5 --> 5 5.5 --> 6 6.5 --> 7 7.5 --> 8 8.5 --> 9 9.5 --> 10 Algandmete keskmine: 5.0 Ümardatud arvude keskmine: 5.5
1.3.2 Funktsioon sorted¶
Iteraatortoega objektide sorteerime. Funktsiooni dokumentatsioon:
sorted?
Signature: sorted(iterable, /, *, key=None, reverse=False) Docstring: Return a new list containing all items from the iterable in ascending order. A custom key function can be supplied to customize the sort order, and the reverse flag can be set to request the result in descending order. Type: builtin_function_or_method
Funktsiooni kasutamise süntaks on järgmine:
lst = ['cccc4','b3','dd2','aaa1'] # Lisaks numberitle järjestame ka tähestikulises järjekorras.
sorted(lst)
['aaa1', 'b3', 'cccc4', 'dd2']
Ole ettevaatlik, kui numbrid on esitatud sõnena:
lst2 = ['100', '20', '1', '5'] # Leksikograafiline järjekord.
lst3 = [int('100'), int('20'), int('1'), int('5')]
print(sorted(lst2))
print(sorted(lst3))
['1', '100', '20', '5'] [1, 5, 20, 100]
it = iter([3, 2, 1])
sorted(it) # Iteraator on iteaatortoega objekt.
[1, 2, 3]
Sorteerida saab iteratiivselt kasutades muid funktsioone (keying functsion):
sorted(lst, key=len) # Võtmesõna key, sotrteerimisel kasuta funktiooni len.
['b3', 'dd2', 'aaa1', 'cccc4']
sorted(lst, key=len, reverse=True)
['cccc4', 'aaa1', 'dd2', 'b3']
sorted(lst, key=lambda x: float(x[-1]))
['aaa1', 'dd2', 'b3', 'cccc4']
1.3.2.1 In-place meetod¶
Funktsiooniga sorted sarnaselt käituv listi meetod sort omad samu argumente. Meetodi dokumentatsioonis on mainitud, et meetod on nn. IN-PLACE meetod. See tähendab, et algne mälus olnud list muudetakse ja kirjutatakse üle. Meetod ei väljasta midagi. Meetodi dokumentatsioon:
lst.sort?
Signature: lst.sort(*, key=None, reverse=False) Docstring: Sort the list in ascending order and return None. The sort is in-place (i.e. the list itself is modified) and stable (i.e. the order of two equal elements is maintained). If a key function is given, apply it once to each list item and sort them, ascending or descending, according to their function values. The reverse flag can be set to sort in descending order. Type: builtin_function_or_method
Kasutamise näide:
lst.sort(key=len, reverse=True)
lst
['cccc4', 'aaa1', 'dd2', 'b3']
Kuna meetod ei väljasta midagi siis pole mõtet seda meetodit kasutada järgmiselt:
new_lst = lst.sort(key=len, reverse=True)
new_lst
Funktsioon sorted loob uue iteraatortoega objekti.
new_lst = sorted(lst, key=len, reverse=True)
new_lst
['cccc4', 'aaa1', 'dd2', 'b3']
1.3.3 Funktsioon map¶
Funktsioon map rakendab meelevaldselt valitud funktsiooni iga iteraatortoega objekti elemendile ja väljastab tulemused iteraatorisse.
Meeldetuletus: Üle iteraatori saab itereerida, iteraator mäletab enda viimast väljakutset (programmi voo andmed säilivad) ning sellele saab rakendada funktsiooni next järgmiste väljakutsete laisaks genereerimiseks, vt. Loeng 7.
Funktsiooni dokumentatsioon:
map?
Init signature: map(self, /, *args, **kwargs) Docstring: map(func, *iterables) --> map object Make an iterator that computes the function using arguments from each of the iterables. Stops when the shortest iterable is exhausted. Type: type Subclasses:
Funktsiooni kasutamise süntaks on järgmine:
a = map(len, ('abc', 'cd', 'efgh'))
print(next(a)) # Esimene iteraat.
print(list(a)) # Funktsioon list itereerib üle iteraatori ammendumiseni.
3 [2, 4]
Kahe argumendiga funktsioonid:
a = map(pow, (2, 2, 2), (1, 2, 3)) # Funktsioon pow eeldab kahte argumenti.
b = map(pow, [2, 2, 2], [1, 2, 3])
print(list(a))
print(list(b))
pow?
[2, 4, 8] [2, 4, 8]
Signature: pow(base, exp, mod=None) Docstring: Equivalent to base**exp with 2 arguments or base**exp % mod with 3 arguments Some types, such as ints, are able to use a more efficient algorithm when invoked using the three argument form. Type: builtin_function_or_method
b = map(lambda x, y: x ** y, [2, 2, 2], [1, 2, 3])
list(b)
[2, 4, 8]
c = map(lambda x, y: x ** y, (2, 2, 2), (1, 2, 3))
for i in c: # Itereerin üle iteraatori c.
print(i)
2 4 8
1.3.4 Funktsioon filter¶
Funktsioon filter tagastab iteraatortoega jada elemendid, mille korral meelevaldselt valitud funktsioon(element) == True. Väljastatud tulemuse andmetüüp on iteraator. Funktsiooni dokumentatsioon:
filter?
Init signature: filter(self, /, *args, **kwargs) Docstring: filter(function or None, iterable) --> filter object Return an iterator yielding those items of iterable for which function(item) is true. If function is None, return the items that are true. Type: type Subclasses:
Funktsiooni kasutamise süntaks on järgmine:
iteraator = filter(bool, [True, 1, (1,), False, [], 0])
iteraator2 = filter(None, [True, 1, (1,), False, [], 0])
print(list(iteraator))
print(list(iteraator2))
[True, 1, (1,)] [True, 1, (1,)]
def positive(x):
if x > 0:
return True
else:
return False
a = filter(positive, [-1, 0, 1, 2])
print(list(a))
[1, 2]
def f(x):
if x > 0:
return x # Positiivne arv = mittetriviaalne täisarv.
print(list(filter(f, [-1, 0, 1, 2]))) # Mittetriviaalse objekt tõeväärtus on True.
[1, 2]
Anonüümne funktsioon ja funktsioon filter:
a = filter(lambda x: x % 2 == 0, range(11))
list(a)
[0, 2, 4, 6, 8, 10]
Sõne on iteraatortoega:
a = filter(bool, 'Juulius on maskott.')
for i in a:
print(i, end=' ')
J u u l i u s o n m a s k o t t .
print(list(filter(None, 'Juulius')), end=' ')
['J', 'u', 'u', 'l', 'i', 'u', 's']
1.3.4.1 Funktsioonide map ja filter võrdlus for-in ja for-in-if avaldistega¶
Funktsioonidega map ja filter ning for-in ja for-in-if avaldistega saab teha samu asju:
| Tegevus | Funktsioonid map ja filter |
for-in avaldised |
|---|---|---|
| Muuta elemente | map(f, data) |
[f(x) for x in data] |
| Filtreerida andmeid | filter(cond, data) |
[x for x in data if cond(x)] |
| Mõlemat (filtreerimine + muutmine) | map(f, filter(cond, data)) |
[f(x) for x in data if cond(x)] |
Näide: Filtreeri ja muuda listi nums arvud, leides paaris arvude ruudud.
data = [1, 2, 3, 4, 5, 6]
f = lambda x: x**2
cond = lambda x: x % 2 == 0
result = list(map(f, filter(cond, data)))
print(result)
result = [f(x) for x in data if cond(x)]
print(result)
[4, 16, 36] [4, 16, 36]
Avaldise kuju on palju selgemalt loetav. Seda peetakse Pythonlikumaks (Pythonic) koodiks. Suurte andmete puhul on funktsioonid kiiremad.
1.3.5 Funktsioon zip¶
Funktsioon zip seob iteraatortoega jadade elemendid elementhaaval korteeži. Väljastatud tulemus edastatakse iteraatorisse. Funktsiooni dokumentatsioon:
zip?
Init signature: zip(self, /, *args, **kwargs) Docstring: zip(*iterables, strict=False) --> Yield tuples until an input is exhausted. >>> list(zip('abcdefg', range(3), range(4))) [('a', 0, 0), ('b', 1, 1), ('c', 2, 2)] The zip object yields n-length tuples, where n is the number of iterables passed as positional arguments to zip(). The i-th element in every tuple comes from the i-th iterable argument to zip(). This continues until the shortest argument is exhausted. If strict is true and one of the arguments is exhausted before the others, raise a ValueError. Type: type Subclasses:
Funktsiooni kasutamise süntaks on järgmine:
a = zip('abc', 'ABC')
print(list(a))
[('a', 'A'), ('b', 'B'), ('c', 'C')]
Maatriksi transponeerimine:
m = [(1, 2), (3, 4)] # Tõlgenda 2x2 maatriksina.
mT = zip(*m) # Transponeeritud M.
print(list(mT))
[(1, 3), (2, 4)]
1.3.6 Funktsioon enumerate¶
Funktsioon enumerate nummerdab iteraatortoega jada elemendid ja väljastab tulemuse korteeži. Väljastatud tulemuse andmetüüp on iteraator. Funktsiooni dokumentatsioon:
enumerate?
Init signature: enumerate(iterable, start=0) Docstring: Return an enumerate object. iterable an object supporting iteration The enumerate object yields pairs containing a count (from start, which defaults to zero) and a value yielded by the iterable argument. enumerate is useful for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ... Type: type Subclasses:
Funktsiooni kasutamise süntaks on järgmine:
a = enumerate(['a', 'b', 'c'])
list(a)
[(0, 'a'), (1, 'b'), (2, 'c')]
a = enumerate(['a', 'b', 'c'], start=2)
list(a)
[(2, 'a'), (3, 'b'), (4, 'c')]
Kasutame sageli itereerimisega koos:
for i, c in enumerate('AUTO'): # Operaator in itereerib üle iteraatori ja pakib korteežid lahti.
print(i, c)
0 A 1 U 2 T 3 O
1.3.7 Funktsioon isinstance¶
Funktsioon isinstance kontrollib objekti kuuluvuse andmetüüpi ning väljastab vastava booli tõeväärtuse. Funktsiooni dokumentatsioon:
isinstance?
Signature: isinstance(obj, class_or_tuple, /) Docstring: Return whether an object is an instance of a class or of a subclass thereof. A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to check against. This is equivalent to ``isinstance(x, A) or isinstance(x, B) or ...`` etc. Type: builtin_function_or_method
Funktsiooni kasutamise süntaks on järgmine:
isinstance(2, int) # Proovi ka klasse list, tuple, jne.
True
isinstance(2.0, float)
True
Sama vastuse saad ka nii:
type(2.0) == float
True
Mitme andmetüübi korraga järgivaatamine:
num_type = (int, float, complex)
print(isinstance('Python', num_type))
print(isinstance(2.0, num_type))
print(isinstance(2, num_type))
False True True
1.3.8 Konstruktorfunktsioon int¶
Teatavasti meile juba tuttav konstruktorfunktsioon int loob või teisendab avaldisi või muid andmetüüpe täisarvudeks. Funktsiooni int saab kasutada ka arvude teisendamiseks erinevatest numbrisüsteemidest kümnendsüsteemi. Väljakutse kujul
int(<x>[, base=10])
kus positsionaalne vaikeväärtusega argument base on teisendatava arvu baas. Funktsiooni int dokumentatsioon:
int?
Init signature: int(self, /, *args, **kwargs) Docstring: int([x]) -> integer int(x, base=10) -> integer Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating point numbers, this truncates towards zero. If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int('0b100', base=0) 4 Type: type Subclasses: bool, IntEnum, IntFlag, _NamedIntConstant
Funktsiooni taolise kasutamise süntaks on järgmine:
a = int('0b10', 0) # Tõlgendab kui täisarvu. Töötab ka 10.
b = int('0b10', base=2) # Töötab ka 10.
c = int('0o123', 8) # Töötab ka 123.
d = int('0x121b', 16) # Töötab ka 121b.
e = int('121b', 16)
f = int('10', 10)
g = int(12.3)
print(a, b, c, d, e, f, g)
2 2 83 4635 4635 10 12
Funktsioon int toetab arvude baase vahemikus 2 kuni 36:
def vali_alus(b):
if 2 <= b <= 36:
arv = b - 1
print(f'Alusega {b} arv {arv} on kümnendsüsteemis {int(str(arv), b)}.')
else:
print('Alus peab olema vahemikus [2, 36]')
vali_alus(36) # Aluseks valiti 36.
Alusega 36 arv 35 on kümnendsüsteemis 113.
1.3.9 Funktsioon eval¶
Funktsioon eval interpreteerib sellele sõnena esitatud avaldise ja väljastab selle väärtuse. Funktsiooni dokumentatsioon:
eval?
Signature: eval(source, globals=None, locals=None, /) Docstring: Evaluate the given source in the context of globals and locals. The source may be a string representing a Python expression or a code object as returned by compile(). The globals must be a dictionary and locals can be any mapping, defaulting to the current globals and locals. If only globals is given, locals defaults to it. Type: builtin_function_or_method
Funktsiooni kasutamise süntaks on järgmine:
eval('2 + 3')
5
NB! Kui avaldis sisaldab jutumärke, kasuta erinevaid.
eval("print('2 + 3')")
2 + 3
Interpreteerimise ajal eemaldame globaalsest skoobist juurdepääsu sisseehitatud objektidele:
eval("abs(-1)", {"__builtins__": None})
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[50], line 1 ----> 1 eval("abs(-1)", {"__builtins__": None}) File <string>:1 TypeError: 'NoneType' object is not subscriptable
Lisame juurdepääsu ainult funktsiooni abs:
eval("abs(-1)", {"__builtins__": None}, {"abs": abs})
1
Lihtne kalkulaator kirjutatud kasutades funktsioone input ja eval:
tehe = input('Sisesta tehe:')
print(f'Tulemus: {tehe} = {eval(tehe)}.')
Tulemus: 1 + 3 = 4.
1.3.10 Funktsioon exec¶
Funktsioon exec interpreteerib sellele sõnes edastatud Pythoni koodi. Funktsiooni dokumentatsioon:
exec?
Signature: exec(source, globals=None, locals=None, /, *, closure=None) Docstring: Execute the given source in the context of globals and locals. The source may be a string representing one or more Python statements or a code object as returned by compile(). The globals must be a dictionary and locals can be any mapping, defaulting to the current globals and locals. If only globals is given, locals defaults to it. The closure must be a tuple of cellvars, and can only be used when source is a code object requiring exactly that many cellvars. Type: builtin_function_or_method
Funktsiooni kasutamise süntaks on järgmine:
exec('print("Hello World!")') # NB! Kui avaldis sisaldab jutumärke, kasuta erinevaid.
Hello World!
code = 'a = 5\nb = 10\nprint("Sum =", a + b)'
exec(code)
Sum = 15
program = '''for i in range(3):
print("Hello World!")
'''
exec(program)
Hello World! Hello World! Hello World!
1.3.11 Funktsioonid all ja any¶
Funktsioonid all ja any itereerivad üle iteraatortoega jada või iteraatori elementide ja rakendavad järjest paarikaupa operaatoreid and funktsioonis all ja or funktsioonis any nii kaua kuni leitakse vastus või kuni jada ammendub.
- Funktsioon
allväljastabTruekui kõik elemendid on tõesed või mittetriviaalsed. - Funktsioon
anyväljastabTruekui vähemelt üks element on tõene või mittetriviaalne.
Funktsiooni all dokumentatsioon:
all?
Signature: all(iterable, /) Docstring: Return True if bool(x) is True for all values x in the iterable. If the iterable is empty, return True. Type: builtin_function_or_method
Funktsiooni all kasutamise süntaks on järgmine:
all([1, '', False])
False
all([1, 'a', True])
True
it = iter([1, 'a', True])
all(it)
True
Funktsiooni any dokumentatsioon:
any?
Signature: any(iterable, /) Docstring: Return True if bool(x) is True for any x in the iterable. If the iterable is empty, return False. Type: builtin_function_or_method
Funktsiooni any kasutamise süntaks on järgmine:
any([1, '', False])
True
any([0, '', False, [], {}, None])
False
1.3.12 Funktsioonid locals ja globals¶
Funktsioon locals tagastab sõnaraamatu mis sisaldab skoobi lokaalsed muutujad. Funktsioon globals tagastab sõnaraamatu mis sisaldab skoobi globaalsed muutujad.
Funktsiooni locals dokumentatsioon:
locals?
Signature: locals() Docstring: Return a dictionary containing the current scope's local variables. NOTE: Whether or not updates to this dictionary will affect name lookups in the local scope and vice-versa is *implementation dependent* and not covered by any backwards compatibility guarantees. Type: builtin_function_or_method
Funktsiooni locals kasutamise süntaks on järgmine:
# locals() # Suur väljatrükk, proovi oma masinas.
local_var = 'local_var'
print(local_var in locals())
print('local_var' in locals())
True True
def fun():
local_muutuja = 'local_objekt'
print(locals())
fun()
{'local_muutuja': 'local_objekt'}
Funktsiooni globals dokumentatsioon:
globals?
Signature: globals() Docstring: Return the dictionary containing the current scope's global variables. NOTE: Updates to this dictionary *will* affect name lookups in the current global scope and vice-versa. Type: builtin_function_or_method
Funktsiooni globals kasutamise süntaks on järgmine:
# globals() # Suur väljatrükk, proovi oma masinas.
global_var = 'global_var'
print(global_var in globals())
print('global_var' in globals())
True True
def fun():
muutuja = 'local_objekt'
fun()
print('muutuja' in globals())
False
def fun():
global muutuja
muutuja = 'local_objekt'
fun()
print('muutuja' in globals())
True
1.3.13 Funktsioon callable¶
Funktsioon kontrollib kas objekt on funktsioon või funktsiooni laadne objekt. Funktsiooni dokumentatsioon:
callable?
Signature: callable(obj, /) Docstring: Return whether the object is callable (i.e., some kind of function). Note that classes are callable, as are instances of classes with a __call__() method. Type: builtin_function_or_method
Funktsiooni kasutamise süntaks on järgmine:
callable(int) # Klass int.
True
m = 1
print(callable(m))
print(callable(any))
print(callable(range))
print(callable('range'))
False True True False
def gen():
yield 1
it = gen()
print(callable(gen()))
print(callable(gen))
print(callable(it))
False True False
def fun():
pass
fun_var = fun
fun_var2 = fun()
print(callable(fun_var))
print(callable(fun_var2))
True False
Funktsioonidel ja funktsiooni-laadsetel objektidel on maagiline meetod __call__. Funktsioon callable kontrollib selle meetodi olemasolu. Rakendame meetodit __call__ funktsioonile fun:
def fun(a):
return a
print(fun(2))
print(fun.__call__(2))
2 2
1.3.14 Funktsioon repr¶
Funktsioon tagastab sõne objekti representatsiooniga. Kasutatakse objekt orienteeritud programmeerimise (OOP) ja silumise kontekstis. Funktsiooni dokumentatsioon:
repr?
Signature: repr(obj, /) Docstring: Return the canonical string representation of the object. For many object types, including most builtins, eval(repr(obj)) == obj. Type: builtin_function_or_method
Funktsiooni kasutamise süntaks on järgmine:
repr(2)
'2'
txt = 'Hello\tWorld'
print(txt)
print(repr(txt))
print(str(txt)) # Inimloetav tekst.
Hello World 'Hello\tWorld' Hello World
f = lambda x: x
print(f)
print(repr(f))
print(str(f)) # Inimloetav tekst.
<function <lambda> at 0x106d67240> <function <lambda> at 0x106d67240> <function <lambda> at 0x106d67240>
Paljudel juhtudel, kui rakendada funktsiooni eval funktsiooni repr väljastatud sõnele siis luuakse uus objekt. Seega repr on justkui eeskiri (kood) objekti loomiseks.
p = [1, 2]
p_new = eval(repr(p))
print(p_new)
print(p is p_new, id(p), id(p_new)) # Kas sama objekt?
[1, 2] False 4409862656 4391828096
1.3.15 Funktsioon divmod¶
Funktsioon tagastab korteeži (x//y, x%y), kus x ja y on arvud. Funktsiooni dokumentatsioon:
divmod?
Signature: divmod(x, y, /) Docstring: Return the tuple (x//y, x%y). Invariant: div*y + mod == x. Type: builtin_function_or_method
Funktsiooni kasutamise süntaks on järgmine:
divmod(10, 3)
(3, 1)
a, b = divmod(10, 3) # Omistusoperaator = pakib korteeži lahti.
print(a, b)
3 1
Kontrollime:
x, y = 10, 3
tup = x//y, x%y
tup
(3, 1)
2 Funktsiooni sulund (function closure)¶
2.1 Mõiste¶
Meeldetuletus 1: Kõrgemat järku funktsioonid (KJF) võtavad vastu ja/või väljastavad funktsioone.
Meeldetuletus 2: Funktsiooni def-blokke saab üksteise sisse pesastada.
Tavaline pesastatud funktsioon. Väljastame pesastatud funktsiooni väärtuse teostades funktsiooni väljakutse peale lausendit return. Seega tegu pole KJF-ga:
def väline():
sõnum = 'Tere'
def sise(): # Pesastatud funktsiooni definitsioon.
print(sõnum) # LEGB reegel.
return sise() # NB! Funktsiooni väärtus.
väline()
Tere
Funktsiooni sulund võimaldab siduda või sulustada andmeid pesastatud funktsiooniga. Hilisemad pesastatud funktsiooni väljakutsed omavad juurdepääsu sulustatud andmetele. Selline käitumine järeldub otseselt muutujate skoobist ja LEGB reeglist:
def väline():
sõnum = 'Tere' # Sulustatud andmed: sõne 'Tere'.
def sise():
print(sõnum) # LEGB reegel.
return sise # NB! Väljastan funktsiooni, funk. on esimese klassi kodanik.
print(väline()) # Väljakutse väljastab funksiooni.
my_func = väline() # my_func ---> funktsioon sise
print(my_func)
print(my_func.__name__) # Dunder atribuut.
my_func() # Kapseldava skoobi sõne 'Tere' pole funktsiooni sise osa aga tuli sellega kaasa.
<function väline.<locals>.sise at 0x106d651c0> <function väline.<locals>.sise at 0x106d651c0> sise Tere
Sulustatud sõne asub kapseldavas skoobis seega saame selle sulustada ka järgmiselt:
def väline(sõnum): # Kaspeldav skoop.
def sise():
print(sõnum) # LEGB reegel.
return sise # NB! Väljastan funktsiooni.
func = väline('Tere tudeng!') # Sulustan kapseldavasse skoopi 'Tere tudeng!'.
func()
Tere tudeng!
def tervitus(tervita):
def meenutus(keda): # LEGB reegel.
print(f'{tervita} {keda}') # LEGB reegel.
return meenutus
viisakus = tervitus('Tere') # Sulustan 'Tere'.
viisakus('seltsimees') # Edastan argumendi pesastatud funktsioonile meenutus.
Tere seltsimees
2.2 Kasutamise näide¶
Funktsiooni sulundi kasutamine HTML koodi genereerimiseks. HTML dokumendi koodi kujul:
<h3>Juuliuse elu</h3>
<p>Juulius Tipikas sai eksamil viie.</p>
automatiseeritud loomine. Selline kood genereerib veebilehele järgmise teksti mis sisaldab ühte kolmanda astme pealkirja ja ühe lõiku teksti:
Juuliuse eluJuulius Tipikas sai eksamil viie. |
def html_tag(tag):
def wrap_text(text):
print('<{0}>{1}</{0}>'.format(tag, text))
return wrap_text
pealkiri = html_tag('h3') # Pealkirja tag.
par = html_tag('p') # Teksti lõigu tag.
pealkiri('Juuliuse elu')
par('Juulius Tipikas sai eksamil viie.')
<h3>Juuliuse elu</h3> <p>Juulius Tipikas sai eksamil viie.</p>
3 Funktsiooni dekoraator ja operaator @¶
Dekoraator võimaldab olemasoleva funktsiooni käitumist muuta ilma funktsiooni definitsiooni ehk sisu muutmata. Dekoraator teeb seda sulundades funktsiooni.
3.1 Dekoreeriv funktsioon ehk dekoraator¶
Näide: Dekoraator mis muudab kaheargumendilise jagamistehet teostava funktsiooni tehte järjekorda kui nimetaja on suurem lugejast:
def dekoraator(func):
def sise(a, b): # Pesastatud funktsioon.
if a < b:
a, b = b, a
return func(a, b) # Sulustatud funktsiooni väljakutse.
return sise # Väljastame pesastatud funktsiooni mis väljastab sulustatud funktsiooni väärtuse.
def jaga(a, b):
return a / b # Lugeja / nimetaja.
print(dekoraator)
print(dekoraator(jaga))
jaga = dekoraator(jaga) # NB! Dekoreerin funktsiooni jaga.
print(jaga(2, 4)) # Nimetaja on suurem.
<function dekoraator at 0x106d644a0> <function dekoraator.<locals>.sise at 0x106d66f20> 2.0
jaga(4, 2) # Nimetaja ei ole suurem.
2.0
3.2 Operaator @¶
Operaator @ võimaldab eelolevat kirjapilti lühendada:
@dekoraator # Asendab rida: jaga = dekoraator(jaga).
def jaga(a, b):
return a / b
jaga(2, 4) # Nimetaja on suurem.
2.0
jaga(4, 2) # Nimetaja ei ole suurem.
2.0
3.3 Kasutamise näide: Puhvermälu (memoization)¶
Fibonacci jada on selline jada mis algab kahe ühega ja iga järgmine liige on kahe eelmise summa:
$$ 1 \quad 1 \quad 2 \quad 3 \quad 5 \quad 8 \quad 13 \quad 21 \quad 34 \quad 55 ~~ \ldots $$
Rekursiivse Fibonacci jada liikmeid $F(n)$, kus $n$ on järjekorranumber, leidva funktsiooni optimeerimine. Aeglane rekursiivne funktsioon on kujul:
def rec_F(n):
'''Leiab n-da fibonacci jada liikme rekursiivselt.'''
if n <= 2:
return 1
return rec_F(n - 2) + rec_F(n - 1)
rec_F(6) # Aeglane ja sisuliselt kasutu kui n >> 1.
8
Mäletatavasti võtab see funktsioon palju aega tulemuste leidmiseks kuna sisemiste funktsioonide väljakutsete arv suure $n$ puhul kasvab röögatult. Programm teostab $2 F(n) - 1$ rekursiivset funktsiooni väljakutset $n$-da jada liikme $F(n)$ arvutamiseks, vt. vrd. Joonis 2.
| Joonis 2. Rekursiivne Fibonacci jada liikme $F(n)$, kus $n$ on täisarv, leidmine. |
Kuna rekursiivne funktsioon teeb korduvaid funktsiooni väljakutseid (vt. Joonis 2) on kasulik eelnevalt leitud väljakutsete tulemused ajutiselt salvestada ning neid taaskasutada.
cache = {} # Tühi sõnaraamat.
def puh_F(n):
# Kui väärtus on mälus kasutame.
if n in cache:
return cache[n] # Edasi ei lähe kui tulemus leitud.
# Arvutame väärtuse.
if n <= 2:
tulem = 1
else:
tulem = puh_F(n - 2) + puh_F(n - 1) # Rekursioon.
# Salvesta tulem ja väljasta vastus.
cache[n] = tulem # Omistan sõnaraamatu võtmele n leitud väärtuse.
return tulem
puh_F(35)
9227465
Üldistame eeltoodud lahenduse luues dekoraatori. Eelnevalt leitud arvutustulemused saame sulustada funktsiooni sulundisse, ehk kasutada dekoraatorit kujul:
def cacheit(func):
cache = {} # Tühi sõnaraamat.
def sisemine(n):
tulem = cache.get(n) # Kontrollin kas sõnaraamatus on tulem.
if tulem is None:
tulem = cache[n] = func(n) # Lisan puuduva tulemuse sõnaraamatusse.
return tulem
return sisemine # Väljastan funktsiooni.
dec_rec_F = cacheit(rec_F) # Dekoreerin.
dec_rec_F(35)
9227465
Sama tulemus kasutades operaatorit @:
@cacheit # Dekoreerin loodud dekoraatoriga.
def alp_dec_rec_F(n): # Uus funktsiooni definitsioon.
if n <= 2:
return 1
return alp_dec_rec_F(n - 2) + alp_dec_rec_F(n - 1)
alp_dec_rec_F(146)
1454489111232772683678306641953
Kui palju kiiremaks me funktsioonid tegime? Teostame analüüsi leides aja mis kulub paljude funktsiooni väljakutse teostamisele. Leiame näiteks Fibonacci jada 30-da liikme. Jupiteri koodirakus ja iPythoni konsoolis saab interpreteerimisele kuulunud aega mõõta maagiliste käskudega (line magic) %%timeit ja %%time:
%%timeit -n 10 -r 7
rec_F(30)
33.1 ms ± 1.33 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Kuna puhvermälu teeb funktsioonid palju kiiremaks teostama 10 miljonit funktsiooni väljakutset.
%%timeit -n 1_000_000 -r 10
puh_F(30)
29.3 ns ± 7.87 ns per loop (mean ± std. dev. of 10 runs, 1,000,000 loops each)
%%timeit -n 1_000_000 -r 10
dec_rec_F(30)
34.8 ns ± 21.5 ns per loop (mean ± std. dev. of 10 runs, 1,000,000 loops each)
%%timeit -n 1_000_000 -r 10
alp_dec_rec_F(30)
31.7 ns ± 8.29 ns per loop (mean ± std. dev. of 10 runs, 1,000,000 loops each)
tingimus1 = True # Ei juhtu midagi.
tingimus2 = False # Tõstatakse erisus.
assert tingimus1, 'Teade 1.'
assert tingimus2, 'Teate 2.'
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) Cell In[105], line 5 2 tingimus2 = False # Tõstatakse erisus. 4 assert tingimus1, 'Teade 1.' ----> 5 assert tingimus2, 'Teate 2.' AssertionError: Teate 2.
a = 1
b = 2
assert a < b, 'Muutuja b peab a-st suurem olema.' # Programm ei peatu.
Kasutamise näide:
def divide(a, b):
assert b != 0, "Nulliga ei saa jagada!"
return a / b
print(divide(5, 2))
print(divide(5, 0))
2.5
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) Cell In[107], line 6 3 return a / b 5 print(divide(5, 2)) ----> 6 print(divide(5, 0)) Cell In[107], line 2, in divide(a, b) 1 def divide(a, b): ----> 2 assert b != 0, "Nulliga ei saa jagada!" 3 return a / b AssertionError: Nulliga ei saa jagada!
def process_data(data):
assert isinstance(data, list), "Data must be a list!"
assert all(isinstance(x, int) for x in data), "All items must be integers!"
return [x * 2 for x in data]
print(process_data([1, 2, 3]))
print(process_data("123"))
[2, 4, 6]
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) Cell In[108], line 7 4 return [x * 2 for x in data] 6 print(process_data([1, 2, 3])) ----> 7 print(process_data("123")) Cell In[108], line 2, in process_data(data) 1 def process_data(data): ----> 2 assert isinstance(data, list), "Data must be a list!" 3 assert all(isinstance(x, int) for x in data), "All items must be integers!" 4 return [x * 2 for x in data] AssertionError: Data must be a list!
5 Konsoolis töötamine ja programmi käivitamine käsurealt¶
5.1 Moodul¶
Pythoni programmifaili ehk mooduli (skripti) laiend on .py. Me saame enda koodi kirjutada mistahes tekstiredaktorisse ning salvestada loodud tekstifaili faililaiendiga ".py". Loodud tekstifaili saab edastada Pythoni interpretaatorile kasutades konsooli.
5.2 Konsool ja ipython käsurea keskkond¶
IPython (ehk Interactive Python) on täiustatud interaktiivne Python konsool (shell), mis pakub palju mugavamaid ja võimsamaid tööriistu kui tavaline Python käsurea keskkond. Seda kasutatakse laialdaselt andmeteaduses, teadusarvutuses, prototüüpimisel ja kiireks koodi katsetamiseks.
Ava Anaconda prompt (Windows) või terminal (macOS, UNIX ja Linux). Sisesta:
ipython
Väljumiseks sisesta Ctrl + D.
5.3 Konsool ja python käsurea keskkond¶
Tavaline Pythoni käsurea keskkond. Ava Anaconda prompt (Windows) või terminal (macOS, UNIX ja Linux). Sisenemiseks sisesta:
python
Väljumiseks sisesta Ctrl + D.
5.4 Konsool ja interpretaator python¶
Eelnevalt valmis kirjutatud mooduli fail on võimalik edastada interpretaatorile käsurealt. Ava Anaconda prompt (Windows) või terminal (macOS, UNIX ja Linux). Navigeeri ennast töökausta kus asub sinu mooduli fail. Leia enda loodud Pythoni moodul ehk programmifaili (.py fail). Käivita programm järgmise käsuga:
python <mooduli nimi>.py
Konsooli kasutamiseks piisab kõigest kolme käsu teadmisest. Konsoolis navigeerid failisüsteemi järgmiselt:
ls(MacOS, UNIX, Linux) võidir(Windows) - Kausta sisu järgivaatamine;cd <alamkausta nimi>- Liigu alamkausta;cd ..- Liigu tagasi, eelmine kaust.
5.4.1 Pythoni avamine erinevates režiimides ja lausend assert¶
Pythoni mooduleid saab avada erinevatel viisidel. Loe abiinfot, sisesta konsooli:
python -h
Dokumentatsioonis on mainitud, et käsk kujul:
python -O <mooduli nimi>.py
Käivitab programmi nn. optimeerimise režiimis. Siin lipp -O (Optimize mode) tähistab optimeerimise režiimi. Selliselt käivitatud programm ignoreerib kõiki lausendeid assert.
6 Integreeritud arenduskeskkond (Integrated Development Environment (IDE))¶
IDE on tarkvara mis võimaldab programmeerijal enda tööd paremini organiseerida ja juhtida. IDE-d on tavaliselt varustatud koodiredaktoriga, koodi kompileerimis- ja/või interpreteerimistööriistadega ning siluriga (degugger).
Siiamaani oleme koodi kirjutanud suhtelistel lihtsates arenduskeskkondades nimega Jupyter Notebook või Jupyter Lab (IPython). Integreeritud arenduskeskkonna tarkvara võimaldab kirjutada pikemaid programme mugavamalt. IDE lubab meil avada ja salvestada .py programmifaile ehk Pythoni mooduleid, omada paremat ülevaadet muutujate väärtustest, projekti failides, jpm.
6.1 Integreeritud arenduskeskkonna Spyder tutvustus¶
Joonis 3 kujutab Spyder IDE graafilist kasutajaliidest. Koodiredaktroisse kirjutatud koodi saab interpreteerida kasutades graafilist liidest (nupud ekraanil) või kasutades klaviatuuri: (Ctrl + Enter = interpreteeri kood ja jää koodiblokki või Shift + Enter = interpreteeri kood ja liigu järgmisesse koodiblokki. Spyderis defineerime uue koodibloki alguse kasutades #%%.
| Joonis 3. Spyder IDE graafiline kasutajaliides, koodiredaktor, IPythoni konsool, dokumentatsiooni aken. |
Juurdepääs projekti failidele on tagatud läbi failihalduri mis on kujutatud Joonisel 4.
| Joonis 4. Spyder IDE graafiline kasutajaliides, failihaldur. |
Loodud muutujate ja muude objektide väärtusi saab järgi vaadata muutujate lehitseja aknas mis on kujutatud Joonisel 5.
| Joonis 5. Spyder IDE graafiline kasutajaliides, muutujate väärtuste aken. |
Spyder projekti koduleht: https://www.spyder-ide.org/
Juhuslik Spyderi IDE-d tutvustav video: https://www.youtube.com/watch?v=zYNRqVimU3Q
6.2 Teised integreeritud arenduskeskkonnad¶
Kui soovid või oled harjunud mõnda muud IDE-d kasutama võid loendutes ja ka eksami praktilise osa ajal seda kasutada. TalTechi tudengite seas on polulaarsed IDE-d näiteks:
- Visual Studio (info: https://visualstudio.microsoft.com) ja
- PyCharm (info ja TalTech tudengile pro versiooni litsents: https://www.jetbrains.com/student/). Litsentsi kasutamiseks loo kasutaja kasutades ülikooli e-maili aadressi.
Kursusetöö¶
Kursusetöö juhend ja näidis¶
Kursusetöö juhend ja näidis on leitav kursuse kodulehelt ja Moodlest. Viidatud näidis demonstreerib muuhulgas kursusetöö vähimat vastuvõetavat mahtu.
Üldine info (Sama info on leitav ka kursuse Moodle veebilehel.):
- Vastavalt kursuse eduka läbimise kriteeriumile ja hindamiseeskirjale on kursusetöö eksamile pääsemise eelduseks.
- Kursusetöö peab olema esitatud enne eksamit.
- Kursusetöö moodustab 5% eksami hindest.
NB! Tudengid kes ei esita kursusetööd saavad kursusehindeks "MI" (mitteilmunud) olenemata sellest kas nad sooritavad eksami või mitte.
Tudengite hindamisest kursusel YFX0500 ja eksamist¶
Esimese loengu jooksul mainiti, et kursusehinne koosneb kolmest osast: kursusetööst mis on eksamile pääsemise eelduseks ja kaheosalisest eksamist:
- Kursusetöö moodustab 5% kursusehindest, maksimaalselt on võimalik teenida kuni 5 pt.
- Eksam moodustab 95% kursusehindest, maksimaalselt on võimalik saada kuni 95 pt.
- Teoreetiline osa moodustab 45% kursusehindest, maksimaalselt on võimalik saada kuni 45 pt. Test toimub Moodles, testi saad võtta terve sessi jooksul. Testi sisu ja vormiga saab enne testi alustamist tutvuda.
- Praktiline osa moodustab 50% kursuse hindest, maksimaalselt on võimalik saada kuni 50 pt. Toimub kohapeal. Kodulehelt ja Moodlest leiad praktiline osa näidise. Näidiseksam lahendatakse läbi viimase nädala praktikumis.
- Ülesanne 1, süntaksireeglite peast tundmine: maksimaalselt kuni 5 pt.
- Ülesanne 2, silumine ja koodi analüüs: maksimaalselt kuni 10 pt.
- Ülesanne 3, algoritmi kasutus, andmete töötlus ja visualiseerimine: maksimaalselt kuni 35 pt.
Osa tudengitest teenivad ka lisapunkte või nn. brownie punkte loengutes ja praktikumides aktiivse osalemise eest. Need punktid (maksimaalselt kuni 10 p tudengi kohta) lisatakse kursusehinde punktisummale. Seega maksimaalselt on võimalik teenida kuni 100 + 10 = 110 p. Teenitud punktisummale vastava kursusehinde määratakse vastavalt kursuse kodulehel avaldatud hindamisskaalale.