Documente Academic
Documente Profesional
Documente Cultură
Transmiterea Argumentelor si
Notiuni Avansate despre Functii
Universitatea Politehnica din Bucureşti
Sumar
❑Argumente
❑Notiuni avansate
PCLP2 –
Note de curs
2 Curs 2
Transmiterea argumentelor
PCLP2 –
Note de curs
4 Curs 2
Referinte...
def f((a, (b, c))): ... # In v2.x, apel cu: f( (1, (2, 3)) )
def f(T): (a, (b, c)) = T # In v3.x, despachetare explicita!
PCLP2 –
Note de curs
7 Curs 2
Tipuri de argumente
PCLP2 –
Note de curs
9 Curs 2
Sintaxa...
• La apel:
▪ argumentele actuale simple sunt determinate pozitional
▪ name=value denota determinare prin numele argumentelor (keywords)
▪ *iterable sau **dict denota argumente de tip secventa/iterabil sau
dictionar care sunt despachetate ca argumente individuale
PCLP2 –
Note de curs
13 Curs 2
Argumente...
• Oricate argumente in def:
>>> def f(*args): print(args) # args e tuple ce >>> f()
colecteaza toate arg. actuale, pozitional
()
>>> f(1)
(1,)
>>> f(1, 2, 3, 4)
(1, 2, 3, 4)
PCLP2 –
Note de curs
18 Curs 2
Argumente...
>>> # Cu argumente cu cuvinte cheie, >>> # c e obligatoriu, cu cuvinte cheie:
obligatorii, b:
>>> def kwonly(a, *, b=1, c, d=2):
>>> def kwonly(a, *, b, c='spam'): print(a, b, c, d)
print(a, b, c)
>>> kwonly(3, c=4)
>>> kwonly(1, b='eggs')
3142
1 eggs spam >>> kwonly(3, c=4, b=5)
>>> kwonly(1, c='eggs')
3542
TypeError: kwonly() missing 1 required
>>> kwonly(3)
keyword-only argument: 'b'
TypeError: kwonly() missing 1 required
>>> kwonly(1, 2) keyword-only argument: 'c'
TypeError: kwonly() takes 1 positional
>>> kwonly(1, 2, 3)
argument but 2 were given
TypeError: kwonly() takes 1 positional
argument but 3 were given
• * inseamna numar fix de argumente, dupa cu
cuvinte cheie! PCLP2 –
Note de curs
19 Curs 2
Ordonarea Argumentelor
• In def, **args NU poate fi urmat de argumente neaparat cu cuvinte
cheie:
>>> def kwonly(a, **pargs, b, c): >>> def kwonly(a, **, b, c): # Nici ** nu e bine
SyntaxError: invalid syntax SyntaxError: invalid syntax
PCLP2 –
Note de curs
21 Curs 2
Rolul argumentelor neaparat cu cuvinte
cheie
• Usureaza definirea functiilor cu numar variabil de argumente
pozitionale si optiuni de configurare (e.g. print())
PCLP2 –
Note de curs
22 Curs 2
Functia min()
• Desi predefinita in Python, cateva variante de implementare:
def min1(*args): def min3(*args):
res = args[0] tmp = list(args)
for arg in args[1:]: tmp.sort()
if arg < res: return tmp[0]
res = arg
return res print(min1(3, 4, 1, 2))
print(min2("bb", "aa"))
def min2(first, *rest): print(min3([2,2], [1,1], [3,3]))
for arg in rest: • Output:
if arg < first: 1
first = arg aa
return first [1, 1]
PCLP2 –
Note de curs
23 Curs 2
minmax()
• Generalizare, calculeaza fie min, fie max:
def minmax(test, *args):
res = args[0] print(minmax(lessthan, 4, 2, 1, 5, 6, 3))
for arg in args[1:]: print(minmax(grtrthan, 4, 2, 1, 5, 6, 3))
if test(arg, res): • Output:
res = arg 1
return res 6
• Functiile pot fi transmise ca argumente,
fiind obiecte in Python
def lessthan(x, y): return x < y # Pentru min
def grtrthan(x, y): return x > y # Pentru max
PCLP2 –
Note de curs
24 Curs 2
Functii pentru multimi
• Intersectie si reuniune:
def intersect(*args): def union(*args):
res = [] res = []
for x in args[0]: # Prima secventa for seq in args: # Parcurgere argumente
if x in res: continue # Fara for x in seq: # Parcurgere secventa
duplicate!
if not x in res:
for other in args[1:]: # Celelalte res.append(x) #
secvente Adaugare element
if x not in other: break #
return res
Lipseste!
else: # Pe for, adauga element
res.append(x)
return res
PCLP2 –
Note de curs
25 Curs 2
Functii...
>>> s1, s2, s3 = "SPAM", "SCAM", "SLAM" [1]
>>> intersect(s1, s2), union(s1, s2) # Doua >>> intersect(s1, s2, s3) # Trei argumente
argumente ['S', 'A', 'M']
(['S', 'A', 'M'], ['S', 'P', 'A', 'M', 'C'])
>>> union(s1, s2, s3)
>>> intersect([1, 2, 3], (1, 4)) # Date mixte, list
['S', 'P', 'A', 'M', 'C', 'L']
si tuple
• Testare cu preschimbarea ordinii secventelor si trasare:
>>> def tester(func, items, trace=True): ('abcdefg', 'abdst', 'albmcnd', 'a')
for i in range(len(items)): ['a']
items = items[1:] + items[:1] ('abdst', 'albmcnd', 'a', 'abcdefg')
if trace: print(items) ['a']
print(sorted(func(*items))) ('albmcnd', 'a', 'abcdefg', 'abdst')
['a']
>>> tester(intersect, ('a', 'abcdefg', 'abdst', ('a', 'abcdefg', 'abdst', 'albmcnd')
'albmcnd')) PCLP2 –
Note de curs
26 ['a'] Curs 2
Functii...
>>> tester(union, ('a', 'abcdefg', 'abdst', >>> tester(intersect, ('ba', 'abcdefg', 'abdst',
'albmcnd'), False) 'albmcnd'), False)
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'l', 'm', 'n', 's', 't'] ['a', 'b']
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'l', 'm', 'n', 's', 't'] ['a', 'b']
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'l', 'm', 'n', 's', 't'] ['a', 'b']
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'l', 'm', 'n', 's', 't'] ['a', 'b']
>>> intersect([1, 2, 1, 3], (1, 1, 4)) # Fara >>> tester(intersect, ('ababa', 'abcdefga',
duplicate 'aaaab'), False)
[1] ['a', 'b']
>>> union([1, 2, 1, 3], (1, 1, 4)) ['a', 'b']
[1, 2, 3, 4] ['a', 'b']
PCLP2 –
Note de curs
27 Curs 2
Emularea functiei print()
• In v2.x: from __future__ import print_function SAU:
import sys print3(1, 2, 3)
def print3(*args, **kargs): print3(1, 2, 3, sep='') # fara separator
sep = kargs.get('sep', ' ') # Valori implicite print3(1, 2, 3, sep='...')
end = kargs.get('end', '\n') print3(1, [2], (3,), sep='...') # Diverse obiecte
file = kargs.get('file', sys.stdout) print3(4, 5, 6, sep='', end='') # Fara linie noua
output = '' print3(7, 8, 9)
first = True # Pt. primul args print3() # Linie noua
for arg in args: import sys
output += ('' if first else sep) + print3(1, 2, 3, sep='??', end='.\n',
str(arg) file=sys.stderr) # Redirectare la stderr
first = False
file.write(output + end)
PCLP2 –
Note de curs
28 Curs 2
Emularea...
• Output: 1...[2]...(3,)
123 4567 8 9
123 1??2??3.
1...2...3
• In v3.x, cu argumente neaparat cu cuvinte cheie:
def print3(*args, sep=' ', end='\n', >>> print3(99, name='bob') # Capteaza
file=sys.stdout): argumente straine!
output = '' TypeError: print3() got an unexpected keyword
first = True argument 'name'
PCLP2 –
Note de curs
31 Curs 2
Sumar
❑Argumente
❑Notiuni avansate
PCLP2 –
Note de curs
32 Curs 2
Concepte in proiectarea functiilor
• Coeziune:
• fiecare functie trebuie sa aiba un singur scop, bine definit
• codul unei functii trebuie sa fie cat mai scurt – cel mult doua
pagini
PCLP2 –
Note de curs
33 Curs 2
Concepte...
• Recursivitate indirecta:
>>> def mysum(L): >>> mysum([1.1, 2.2, 3.3, 4.4])
if not L: return 0 # Punct fix! 11.0
return nonempty(L) # nonempty
apeleaza mysum
>>> def nonempty(L):
return L[0] + mysum(L[1:]) #
Recursivitate indirecta
PCLP2 –
Note de curs
37 Curs 2
Recursivitate...
• Cu numar variabil de argumente (pozitionale):
>>> def mysum(*pargs): (2, 3)
zero = None (3,)
def asum( *pargs ): # asum e recursiva! 6
nonlocal zero >>> mysum( (1,), (2,), (3, 4 ) ) # tuple
if not pargs: return zero ((1,), (2,), (3, 4))
print( pargs ) ((2,), (3, 4))
a, *b = pargs ((3, 4),)
zero = type( a )() # Element neutru (1, 2, 3, 4)
la adunare >>> mysum( 's', 'p', 'a', 'm' ) # str
return a + asum( *b )
('s', 'p', 'a', 'm')
return asum( *pargs )
('p', 'a', 'm')
>>> mysum() ('a', 'm')
>>> mysum( 1, 2, 3 ) # int
('m',)
(1, 2, 3) PCLP2 –
Note de curs
38
'spam'
Curs 2
Iteratie vs. recursivitate
• Parcurgere cu while:
>>> L = [1, 2, 3, 4, 5] >>> sum
>>> sum = 0 15
>>> while L:
sum += L[0]
L = L[1:]
PCLP2 –
Note de curs
43 Curs 2
Examinarea functiilor
• Functiile sunt obiecte cu operatii definite, e.g. apelul:
>>> def func(a): >>> func(8) # Apel clasic de functie
b = 'spam' 'spamspamspamspamspamspamspamspam'
return b * a
• Functiile au atribute generice, de sistem:
>>> func.__name__ # Nume functie >>> dir( func.__code__ )
'func' ['__class__', '__delattr__', '__dir__', '__doc__',
>>> dir(func) '__eq__', '__format__', '__ge__',
...
['__annotations__', '__call__', '__class__',
'__closure__', '__code__', 'co_argcount', 'co_cellvars', 'co_code',
'co_name', 'co_names', 'co_nlocals',
...
'co_stacksize', 'co_varnames']
'__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__'] >>> func.__code__.co_varnames
('a', 'b')
>>> func.__code__ # Obiect de tip cod
>>> func.__code__.co_argcount
<code object func at 0x0000027F33FB91E0, file
Note de curs PCLP2 –
44 "<pyshell#79>", line 1> 1
Curs 2
Atribute de functii
• Utilizatorul poate atasa atribute functiilor:
>>> func 'Button-Press'
<function func at 0x0000027F33FB94C8> >>> dir(func)
>>> func.count = 0 # Atributul count ['__annotations__', '__call__', '__class__',
>>> func.count += 1 ...
>>> func.count '__subclasshook__', 'count', 'handles']
1
>>> func.handles = 'Button-Press' # Atributul
handles
>>> func.handles
PCLP2 –
Note de curs
45 Curs 2
Adnotarea functiilor in v3.x
• Adnotarile se aplica argumentelor sau/si rezultatului functiei, in
antet:
>>> def func(a: 'spam', b: (1, 10), c: float) -> >>> func(1, 2, 3)
int:
6
return a + b + c
PCLP2 –
Note de curs
48 Curs 2
Utilizari ale lambda
• Desi optionala, lambda se foloseste la crearea tabelelor de salt:
L = [lambda x: x ** 2, # Functii inline for f in L:
lambda x: x ** 3, print(f(2)) # Afiseaza 4, 8, 16
lambda x: x ** 4] # O lista cu 3 functii print(L[0](3)) # Afiseaza 9
• lambda si GUI:
>>> from tkinter import Button, mainloop >>> mainloop() # La fiecare click...
>>> x = Button( Spam
text='Press me', Spam
command=(lambda:print('Spam\n')))
>>> x.pack() • tkinter GUI API
PCLP2 –
Note de curs
51 Curs 2
Programare functionala
• Cu functia map(), se aplica functii asupra iterabilelor:
>>> counters = [1, 2, 3, 4] • Cu map:
>>> updated = [] >>> def inc(x): return x + 10
>>> for x in counters: >>> list(map(inc, counters)) # Se executa inc pt.
fiecare element din counters
updated.append(x + 10)
[11, 12, 13, 14]
>>> updated
[11, 12, 13, 14] >>> list(map((lambda x: x + 10), counters)) #
Cu lambda in loc de inc
[11, 12, 13, 14]
>>> pow(3, 4) # 3**4 Cu N secvente, functia aplicata de
map trebuie sa aiba N argumente!
81
>>> list(map(pow, [1, 2, 3], [2, 3, 4])) #
1**2, 2**3, 3**4
[1, 8, 81]
PCLP2 –
Note de curs
52 Curs 2
Programare...
>>> list(map(inc, [1, 2, 3, 4])) >>> [inc(x) for x in [1, 2, 3, 4]] # Colectie echiv.
[11, 12, 13, 14] [11, 12, 13, 14]
PCLP2 –
Note de curs
53 Curs 2
Programare...
• Cu functia functools.reduce(), se combina iterabilele intr-un singur
rezultat:
>>> from functools import reduce # In v3.x >>> # Echivalent, suma, cu instructiuni:
>>> # Suma: >>> L = [1,2,3,4]
>>> reduce((lambda x, y: x + y), [1, 2, 3, 4]) >>> res = L[0]
10 >>> for x in L[1:]:
>>> # Produs: res += x
>>> reduce((lambda x, y: x * y), [1, 2, 3, 4]) >>> res
24 10
>>> def myreduce(function, >>> myreduce((lambda x, y: x + y), [1,
sequence): # Cod echiv. 2, 3, 4, 5])
tally = sequence[0] 15
for next in sequence[1:]: >>> myreduce((lambda x, y: x * y), [1,
2, 3, 4, 5])
tally = function(tally, next)
120 PCLP2 –
return tally Note de curs
54 Curs 2