6. funkcija je FCC
first class citizen - is an entity which supports all
the operations generally available to other
entities.
These operations typically include being passed
as a parameter, returned from a function, and
assigned to a variable.
https://en.wikipedia.org/wiki/First-class_citizen
7. funkcija kao i svaki drugi
objekt
>>> def f(s):
... "pydoc ..."
... return "hello %s" % s
!
>>> type(f)
<type ‘function’>
!
>>> dir(f)
['__call__', '__class__', '__closure__', '__code__',
'__defaults__', '__delattr__', '__dict__', '__doc__',
'__format__', '__globals__', '__init__', '__module__', '__name__',
… 'func_closure', 'func_code', 'func_defaults', 'func_dict',
'func_doc', 'func_globals', ‘func_name’]
>>> g = f # dodijeli varijabli
>>> f(f) # proslijedi kao parametar
'hello <function f at 0x10b66bb90>'
8. par atributa …
>>> def f(s):
... "pydoc dokumentacija"
... return "hello %s" % s
!
!>>> f.__globals__
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'f':
<function f at 0x10b66b5f0>, '__doc__': None, '__package__': None}
!
>>> f.__doc__
'pydoc dokumentacija'
!
>>> f.__name__
'f'
!
>>> f.__code__
<code object f at 0x10b639030, file "<stdin>", line 1>
!
>>> f.__closure__
>>> f.__defaults__
>>> f.__dict__
9. lambda expression
• izraz, nije naredba, vrlo ograničeno, ne može sadržavati naredbe
• vraća objekt funkcije
• korisno: gdje god može ići izraz, tamo se može staviti lambda
>>> f = lambda x: x*2
>>> f(3) -> 6
>>> type(f); dir(f)
<type ‘function’>, ['__call__', ‘__class__’..
>>> (lambda x: x*2)(3) -> 6
10. objekt kao funkcija
• vrlo jednostavno -> implementirati __call__ metodu
• objekt nije tipa “function” već F, ipak se razlikuje od standardne funkcije
!
class F(object):
def __call__(self, s):
return "hello %s" % s
!
>>> f = F()
>>> f("world")
'hello world'
!
>>> callable(f)
True
>>> dir(f)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', …]
11. klasa je object factory
funkcija
class C(object):
pass
!
>>> callable(C)
True
!
# klasa je funkcija koja vraća novi objekt
>>> C()
<__main__.C object at 0x10b669bd0>
>>> C()
<__main__.C object at 0x10b691b33>
12. metoda = priljepljena funkcija
class C(object):
def m(self, s):
return "method %s" % s
!
>>> C.m, C().m
<unbound method C.m>, <bound method C.m of <__main__.C object at 0x10b669bd0>>
!
>>> dir(C.m)
['__call__', … , 'im_class', 'im_func', 'im_self']
!
>>> C.m==C().m
False
!
>>> C.m.im_self, C().m.im_self
None, <__main__.C object at 0x10b669bd0>
!
>>> C().m.im_func, C().m.im_func == C.m.im_func
<function m at 0x10b66b5f0>, True
13. dinamička metoda
- dodati na klasu
class C(object):
pass
!
>>> def m(self, s):
return "hello %s" % s
!
>>> C.m = m
>>> C().m("world")
'hello world'
14. dinamička metoda
- dodati na objekt
class C(object):
pass
!
>>> def m(self, s):
return "hello %s" % s
>>> o = C()
>>> import types
>>> o.m = types.MethodType( m, o )
>>> o.m("world")
'hello world'
15. s metodom je jednostavnije
class C(object):
def __str__(self):
return "Object %s" % id(self)
__repr__ = __str__
!
>>> o = C()
>>> repr(o), str(o)
'Object 4486241936’, 'Object 4486241808'
!
>>> o.x = o.__str__
>>> o.x()
'Object 4486241808'
16. vlastiti atribut funkcije
class C(object):
def m(self):
return 1
m.is_test = 1
!
def x():
return 2
x.is_test = 3
!
>>> x.is_test
3
>>> C.m.is_test
1
18. self
“self” u metodi je samo konvencija, tj. ovo je
valjani kod:!
!
class C(object):
def set_x(zeko_mrkva, x):
zeko_mrkva.x = x
!
>>> o = C(); o.set_x(3); print o.x
3
19. high order functions
(also functional form, functional or functor) is a
function that does at least one of the following:
1. takes one or more functions as an input!
2. outputs a function!
All other functions are first-order functions.
https://en.wikipedia.org/wiki/Higher-order_function
21. i još …
def add(a,b):
return a+b
!
def subs(a,b):
return a-b
!
def get_f_op(op_name):
return globals()[op_name] # vraća funkciju
!
>>> get_f_op("add")
<function add at 0x10b66ba28>
!
>>> get_f_op("add")(3,4)
7
>>> get_f_op("subs")(3,4)
-1
22. funkcijska paradigma
a style of building .. computer programs, that
treats computation as the evaluation of
mathematical functions and avoids state and
mutable data.
emphasizes functions that produce results that
depend only on their inputs and not on the
program state — i.e. pure mathematical functions.
https://en.wikipedia.org/wiki/Functional_paradigm
23. laički
• nema “side-effects”
• nema mutable objekata tj.
svaka promjena -> novi objekt
• u praksi:
funkcije, immutable objekti: primitivni, liste, dictionaries
flow: funkcija zove funkciju koja zove funkciju koja
prosljeđuje funkciju koja vraća funkciju …
24. python i funkcijska
paradigma
• python se klasificira kao “multi-paradigm”
• “implementira” i funkcijsku paradigmu
• u praksi se vidi puno više objektne paradigme
• funkcijsko - nasljeđe i novije
26. builtins
for i, x in enumerate([10, 20, 30]):
print "%s. %s, " % (i,x),
0. 10, 1. 20, 2. 30,
!
for a,b,c in zip([1,2,3], [10,20], [100, 200]):
print "%s %s %s, " % (a,b,c),
1 10 100, 2 20 200,
!
# sorted prima i funkcije za određivanje redoslijeda
for a in sorted([3,2,4,1], reverse=True):
print a,
4,3,2,1
!
reversed, (x)range …
27. list comprehension
Jedan dio ovih funkcija se može uspješno zamijeniti s “list comprehension”!
!
Primjeri:!
!
>>> map(lambda x: x+1, (1,2,3))
==
>>> [x+1 for x in (1,2,3)]
!
!
>>> filter(lambda x: x>1, (1,2,3))
==
>>> [x for x in (1,2,3) if x>1]
!
29. operator
Standard operators as functions - comparison,
bool, math, etc.!
!
>>> from functools import partial
>>> from operator import add
>>> add_3 = partial(add, 3)
>>> add_3(2)
5
30. generators
• generator expression!
>>> ge = (x+1 for x in range(3)); print ge
<generator object <genexpr> at 0x10b664aa0>
>>> tuple(ge)
(1,2,3)
• yield u funkciji -> poseban oblik funkcije - coroutine, vraća generator object
• coroutine: allow multiple entry points for suspending and resuming execution at
certain locations (https://en.wikipedia.org/wiki/Coroutine)
!
def go(n):
for x in range(n):
yield x+1
!
>>> go(3)
<generator object go at 0x10b664af0>
>>> tuple(go(3))
(1,2,3)
31. generators
• yield zaustavlja izvođenje funkcije, pamti stanje i prenosi izvođenje natrag na pozivatelja
• poziv generator_object.next() vraća generatorsku funkciju u isti kontekst gdje je stala te funkcija
nastavlja do sljedećeg yield-a ili kraja funkcije
• moguće je iz pozivatelja slati informacije natrag generatoru sa generator_object.send()
!
def genfun(n):
print “in”
for x in range(n):
y = yield x+1
print “got”, y
!
>>> go = genfun(3)
>>> go.send(None); print “x=“,x
in, x=0
!
>>> x = go.send(10); print “x=“,x
got 10, x=1
!
>>> x = go.send(13); print “x=“,x
got 13, x=2
32. itertools
Functions creating iterators for efficient looping. !
Hrpa brzih funkcija za razno razne manipulacije listama, dictionary-ma i sl. - često primaju funkcije kao
parametre:
!
Functions creating iterators for efficient looping
!
count() cycle() repeat()
!
Iterators terminating on the shortest input sequence:
!
chain() compress() dropwhile() groupby()
ifilter() ifilterfalse() islice() imap()
starmap() tee() takewhile()
izip() izip_longest()
!
Combinatoric generators:
!
product() permutations()
combinations() combinations_with_replacement()
product('ABCD', repeat=2) permutations('ABCD', 2)
combinations('ABCD', 2) combinations_with_replacement('ABCD', 2)
33. closures
is a function or reference to a function together
with a referencing environment—a table storing
a reference to each of the non-local variables
https://en.wikipedia.org/wiki/Closure_(computer_programming)
34. python function scope
• bitno je znati da se “vanjske” varijable vide
def f(a):
b = 1
print globals().keys()
print locals().keys()
!
>>> f(3)
['__builtins__', '__name__', 'f', '__doc__',
'__package__']
['a', ‘b']
• kad je potrebno mijenjati jednostavnu “vanjsku” varijablu - koristiti “global”
statement
35. closures u pythonu
funkcija unutar funkcije “vidi” lokalne objekte
“vlasnika” funkcije
!
def f(a):
b = [1,2]
def closure(c):
return a+b+c # vidi a i b
return closure([3,4])
!
>>> f([0]) # poziva inner funkciju
[0, 1, 2, 3, 4]
36. funkcija vraća funkciju
funkcija koja vraća funkciju prilagođenu prema ulaznim parametrima prve funkcije
!
def f(a):
b = [1,2]
def closure(c):
return a+b+c # vidi a i b
return closure
!
>>> fun = f([0]) # vraća funkciju
<function closure at 0x10b66bde8>
!
>>> fun.__closure__ # je li se tko sjeća ovoga?
(<cell at 0x10b6771d8: builtin_function_or_method object at 0x10b6765f0>,
<cell at 0x10b677168: list object at 0x10b671758>)
!
>>> fun([5,6])
[0, 1, 2, 5, 6]
37. dekorator funkcija - uvod
dekorator funkcije je funkcija (1) koja za prvi ulazni parametar prima
funkciju (2) i vraća drugu funkciju (3) koja koristi parametar funkciju (1)
!
def f(fun, a): # (1) (2)
def closure(c): # (3)
print "before calling %s(%s, %s)" % (fun.__name__, a,c)
return fun(a,c) # (2)
return closure
!
>>> def add(x,y): return x+y # (2)
>>> fun = f(add, [0]) # vraća funkciju (3)
<function closure at 0x10b66bde8>
!
>>> fun([7,8]) # poziva (3)
before calling add([0], [7, 8])
[0, 7, 8]
38. dekorator funkcija
sugar-syntax je @:
!
def deco(fun):
b = [1,2]
def closure(c):
print "before calling %s(%s, %s)" % (fun.__name__, a,c)
return fun(a,c)
return closure
!
@deco # što je isto kao: add = deco(add)
def add(x,y):
return x+y
!
>>> add([7,8])
before calling add([1, 2], [7, 8])
[1, 2, 7, 8]
39. dekorator s parametrima
funkcija u funkciji u funkciji, 4 funkcije u igri, uff …
def dec_with_args(dec_arg1, dec_arg2):
def my_decorator(func):
def wrapped(fun_arg1, fun_arg2) :
return func(fun_arg1, fun_arg2)
return wrapped
return my_decorator
!
@dec_with_args("Leonard", "Sheldon")
def dec_fun(fun_arg1, fun_arg2):
print ("{0} {1}".format(fun_arg1, fun_arg2))
!
dec_fun("Rajesh", "Howard")
40. kako objekt može biti funkcija…
to daje alternativnu metodu za implementaciju dekoratora
class deco(object):
def __init__(self, fun):
self.fun = fun
!
def __call__(self, c):
return self.fun([4], c)
!
@deco
def add2(x, y): return x+y
!
>>> add2([1])
[4, 1]
41. dekorator - zadnji slide :)
• osim nad funkcijom - dekorator možemo napraviti i nad:
• metodom
• klasom
• posebna problematika napraviti robustan dekorator koji
radi i za klase i za metode i za funkcije
• koristiti functools.wraps za izradu dekoratora
• mogu se nizati - tj. više dekoratora nad istom funkcijom
42. i … to bi bilo to
Hvala na strpljenju!
Pitanja?
!
robert.lujo@gmail.com
@trebor74hr