funkcija, objekt, python

Post on 02-Jul-2015

316 Views

Category:

Software

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Funkcije u pythonu, funkcijska paradigma, high order functions, first class citizens, closures, decorators

TRANSCRIPT

funkcija, objekt, python

!Robert Lujo

o meni

• software

• profesionalno 17 g.

• python od 2.0, django od 0.96

• freelancer

• ostalo na linkedin-u

funkcija

a function/subroutine/procedure/routine/method/subprogram is a sequence of program instructions that perform a specific task, packaged as a unit

https://en.wikipedia.org/wiki/Function_(programming)

funkcija u pythonu

Sve što zadovoljava:

callable(f)

hasattr(f, “__call__”)

primjer

def f(s):

print(“hello”, s)

>>> callable(f); hasattr(f,”__call__”)

True, True

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

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>'

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__

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

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__', …]

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>

metoda = priljepljena funkcijaclass 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

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'

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'

s metodom je jednostavnijeclass 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'

vlastiti atribut funkcijeclass 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

argumenti funkcijedef f(a1, *args, **kwargs): print a1, args, kwargs !

>>> f(1,2,x=3) 1 (2,) {'x': 3} !

>>> f(1, *[2,3], **{“x”: 4}) 1 (2, 3) {'x': 4}

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

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

nabacujemo se funkcijama

def add(a,b): return a+b !

def operation_with_3(f_op, a): return f_op(a,3) !

>>> operation_with_3(add, 2) 5

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

funkcijska paradigmaa 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

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 …

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

builtins>>> map(lambda x: x+1, (1,2,3)) [2, 3, 4] !>>> reduce(lambda r,n: r + [r[-1]+n], [1,2,3], [0]) [0, 1, 3, 6] !>>> filter(lambda x: x>1, (1,2,3)) [2, 3] !>>> any((0,””,True)), all((0,””, True)) True, False !>>> min((3,2,4)), max((3,2,4)) 2 4

builtinsfor 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 …

list comprehensionJedan 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] !

functools.partial

def add(a,b): return a+b !

>>> from functools import partial >>> add_3 = partial(add, 3) >>> add_3(2) 5

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

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)

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

itertoolsFunctions 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)

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)

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

closures u pythonufunkcija 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]

funkcija vraća funkcijufunkcija 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]

dekorator funkcija - uvoddekorator 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]

dekorator funkcijasugar-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]

dekorator s parametrimafunkcija 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")

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]

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

i … to bi bilo to

Hvala na strpljenju!

Pitanja?

!

robert.lujo@gmail.com

@trebor74hr

top related