Funkcje - przypomnienie
Przykłady
def intersect(seq1, seq2):� return [x for x in seq1 if x in seq2]
��print(intersect([1,2,3], (2,3)))
[2, 3]
def fun(a: "int", b: "Cos co mozna mnozyc"):� print(a)� def fun_in_fun(a):� print(a*3)� fun_in_fun(b)� fun.c = 12�
fun(2, 5)�fun(2, "spam")�print(fun.c)
print(fun.__annotations__)
2�15�2�spamspamspam�12�{'b': 'Cos co mozna mnozyc', 'a': 'int'}
polimorfizm
adnotacje (py 3+)
obiekt
Argumenty w funkcji
Nasze stałe dla przykładów:
N = 5�power_of_two = [x ** 2 for x in range(N)]
def fun(a):� a = 23��fun(N)�fun(power_of_two)�print(N, power_of_two)
def fun_mutable(a):� a.append(9)��fun_mutable(power_of_two)�print(power_of_two)
def fun_default(a=[]):� a.append(2)� print(a)��for _ in range(4):� fun_default()
(5, [0, 1, 4, 9, 16])
[0, 1, 4, 9, 16, 9]
[2]
[2, 2]
[2, 2, 2]
[2, 2, 2, 2]
Reguła LEGB w funkcjach
L
E
G
B
Graficznie
Zakresy
def show_enclosing(a):� def enclosing():� print("Enclosing: %s" % a)� enclosing()��show_enclosing(5)
def show_local():� x = 23� print("Local: %s" % x)��show_local()
x = 43�def show_global():� print("Global %s" % x)��show_global()
def show_built():� print("Built-in: %s" % abs)��show_built()�import builtins # py3�print(dir(builtins))�# print(dir(__builtins__)) #py 2.7
Enclosing: 5
Local: 23
Global 43
Built-in: <built-in function abs>
Zakresy
x = 43�def what_x():� print(x)� x = 4��what_x()
UnboundLocalError: local variable 'x' referenced before assignment
x = 43�def encl_x():� x = 23� def enclosing():� print("Enclosing: %s" % x)� enclosing()��encl_x()
x = 43�def what_about_globals():� global x� x = 37� print("In function %s" % x)��what_about_globals()�print("After function %s" % x)
Enclosing: 23
In function 37
After function 37
x = 43�def what_about_nonlocals():� x = 28� print("Function before enclosing: %s" % x)� def enclosing():� nonlocal x� x = 23� print("Enclosing %s" %x)� enclosing()� print("Function %s" %x)��what_about_nonlocals()
Function before enclosing: 28
Enclosing 23
Function 23
python 3+
Zakresy
x = 43�def main_import():� import __main__� __main__.x = 33��main_import()�print(x)
def fun():� x = fun.l*23� fun.l += 2� print(x)�fun.l = 1�fun()�fun()
33
23
69
Tak lepiej nie kodzić :)
Fabryki funkcji
W skrócie funkcje tworzące nowe funkcje.
def powerer(power):� def nested(number):� return number ** power� return nested
square = powerer(2)��print(square(10))�print(powerer(2)(4))
functions = [powerer(i) for i in range(1,5)]��print(functions[3](4))
def co_ile(start):� def nested(label):� print(label, nested.state)� nested.state += 1� nested.state = start� return nested���f = co_ile(0)�f("foo")�f("bar")��g = co_ile(42)�g("foo")�f("foo")
100
16
256
('foo', 0)�('bar', 1)
�('foo', 42)�('foo', 2)
Funkcje anonimowe
Funkcje anonimowe tworzy się za pomocą wyrażenia lambda
x = lambda : 2
def x():� return 2
print((lambda x,y: x*y)(2,4))
l = [(lambda x: x**2 if x > 2 else x), (lambda x: x**3), (lambda x: x**4)]�for f in l:� print(f(2))
8
2
8
16
Funkcje anonimowe - przyklady
import random�lista_nieuporzadkowana = [(elem,random.randint(0, 30)) for elem in range(10)]�lista = [x for x in range(10)]��print(lista_nieuporzadkowana)
print(sorted(lista_nieuporzadkowana, cmp = lambda x, y: cmp(x[1], y[1]))) #tak nie robic! duzo porownan�
print(sorted(lista_nieuporzadkowana, key = lambda x: x[1]))��print(sorted(lista_nieuporzadkowana))
[(4, 15), (2, 19), (3, 20), (0, 22), (1, 24)]
[(4, 15), (2, 19), (3, 20), (0, 22), (1, 24)]
[(0, 22), (1, 24), (2, 19), (3, 20), (4, 15)]
[(0, 22), (1, 24), (2, 19), (3, 20), (4, 15)]
#wywodzi sie z jezykow funkcyjnych w py 3 trzeba dodac list�print(map(lambda x: x**2, lista))�print(filter(lambda x: x>0, range(-5,5)))�print(reduce(lambda a,b : a+b, range(0, 10)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[1, 2, 3, 4]
45
Generatory - jednorazowe iteratory
Funkcje moga zwracać wartość cząstkową, zapisując swój aktualny stan, aby po wznowieniu mogły kontynuować od miejsca gdzie się ostatnio zatrzymała.
def gensquares(n):� for i in range(n):� yield i ** 2��print(gensquares(10))��print(list(gensquares(10)))
(5*i for i in range(20))
<generator object gensquares at 0x1043a4be0>
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<generator object <genexpr> at 0x1043a4c30>
def f():� yield #None� print(2)� yield��x = f()�next(x)�next(x)
2
Iteracja w pythonie
def gensquares(n):� for i in range(n):� yield i ** 2
x = gensquares(3)
next(x)
next(x)
next(x)
next(x)
0
1
4
StopIteration
Tak samo każdy obiekt iterowalny np. lista:
l = [1,2,3]�i = iter(l)�next(i)�next(i)�next(i)�next(i)
1
2
3
StopIteration
W skrócie kiedy korzystamy z for’a to python sam robi sobie iterator i przechodzi po nim aż do StopIteration :)
Gdzie są generatory + bonus
def gen():� for i in range(10):� x = yield i� print(x)��x = gen()
�print(next(x))�print(next(x))�print(x.send(43))�print(next(x))�print(next(x))
Wysłanie czegoś do generatora
0�
None
1�
43
2�
None
3�
None
4
Importowanie
from module import name1, name2��import module�name1 = module.name1�name2 = module.name2�del module
#jestesmy w A.B.C��from . import D # A.B.D�from .. import E # A.E�from .D import X # A.B.D.X�from ..E import X # A.E.X
Context manager czyli with
with wyrażenie [as zmienna]:
block_with
Wyrażenie jest context managerem czyli wykonuje przed rozpoczęciem i po skończeniu funkcję block_with (ustawienie i wyczyszczenie danych).
with open("file", 'w') as f:� f.write("Hello file")
Nie musimy zamykać pliku, context manager zrobi to za nas
Tworzy się je za pomocą klas, istnieje też skrót from contextlib import contextmanager , który jest dekoratorem - o tym na następnej prezentacji! :)
Pliki
Mamy 3 tryby otwierania plików: r, w, a (read, write, append).
Możemy dodać do każdego + co oznacza aktualizacje. Więcej o trybach.
f = open("file", "r+")�all_file = f.read()�f.write("\nEnd")�f.close()��with open("file", "r+") as f:� for line in f:� print(line.rstrip())� f.seek(0)� print(f.read(4))� f.seek(11)� print(f.readline())� f.seek(0)� print(f.readlines())
Hello file
End
Hell
End
['Hello file\n', 'End']
Zadania
0. Wszystkie rozwiązania napisz w postaci funkcji w module o nazwie rozwiazania.py
1. Wygeneruj plik zawierajacy pierwiastki kolejnych liczb od 0 do 36 - w każdej linii jeden.
2. Wczytaj plik z poprzedniego zadania. Oblicz sumę pierwiastków. Następnie dopisz na końcu pliku otrzymany wynik.
3. Napisz funkcje tworząca funkcje (fabryka) która przyjmuje stringa, a zwraca ile razy (dotychczas) został podany ten właśnie string jako argument - wykorzystaj zagnieżdżone def w def oraz metodę setdefault dla słowników.
4. Napisz generator dla kolejnych potęg liczby 2, aż do 10. Zastosuj obie składnie podane na wykładzie.
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024
counter = fun()�counter("spam")�counter("food")�counter("food")
0
0
1
Dostępne pod adresem: tinyurl.com/pycircle
Zadania
5. Wygeneruj liste 10 losowych liczb z zakresu 25 do 75. Posortuj je w kolejności odwrotnej. (największa liczba ma być pierwszą w liście). Czy potrzebna jest do tego lambda?
np. [73, 62, 55, 51, 49, 45, 44, 42, 29, 27]
6. Wykorzystując funkcje anonimowe wyfiltruj z listy [9,3,24,5,12,17,16, 93,1,203, 27, 93] liczby podzielne przez 3.
[9, 3, 24, 12, 93, 27, 99]
7. Napisz funkcje która bedzie zachowywała się tak samo jak join za pomocą funkcji reduce() oraz funkcji anonimowych(w pythonie 3.3 reduce jest w module functools)
print(fjoin(" ", ['foo', 'bar', 'spam']))
foo bar spam