Parametri si Argumente in Python
Terminologie
- Parametru: Variabila in definitia functiei
- Argument: Valoarea transmisa la apel
def salut(nume): # 'nume' este PARAMETRU
print(f"Salut, {nume}!")
salut("Ana") # "Ana" este ARGUMENT
Argumente Pozitionale
Se potrivesc cu parametrii in ordinea in care sunt dati:
def prezinta(nume, varsta, oras):
print(f"{nume}, {varsta} ani, din {oras}")
# Ordinea conteaza!
prezinta("Ana", 20, "Cluj") # Ana, 20 ani, din Cluj
prezinta(20, "Ana", "Cluj") # 20, Ana ani, din Cluj (gresit!)
Argumente Keyword (cu nume)
Specifici explicit numele parametrului:
def prezinta(nume, varsta, oras):
print(f"{nume}, {varsta} ani, din {oras}")
# Ordinea nu mai conteaza
prezinta(varsta=20, oras="Cluj", nume="Ana") # Ana, 20 ani, din Cluj
# Combinatie - pozitionale INAINTE de keyword
prezinta("Ana", oras="Cluj", varsta=20) # Ana, 20 ani, din Cluj
Valori Implicite (Default)
Parametrii pot avea valori prestabilite:
def salut(nume, salutare="Salut"):
print(f"{salutare}, {nume}!")
salut("Ana") # Salut, Ana!
salut("Ana", "Buna ziua") # Buna ziua, Ana!
salut("Ana", salutare="Ciao") # Ciao, Ana!
Ordinea parametrilor:
Parametrii cu valori implicite trebuie sa fie dupa cei fara:
# CORECT
def functie(obligatoriu, optional="default"):
pass
# GRESIT - SyntaxError
def functie(optional="default", obligatoriu):
pass
ATENTIE - Valori mutabile ca default:
# GRESIT - bug clasic!
def adauga(element, lista=[]):
lista.append(element)
return lista
print(adauga(1)) # [1]
print(adauga(2)) # [1, 2] - Nu [2]!
print(adauga(3)) # [1, 2, 3]
# CORECT
def adauga(element, lista=None):
if lista is None:
lista = []
lista.append(element)
return lista
*args - Argumente Pozitionale Variabile
*args colecteaza argumente pozitionale suplimentare intr-un tuple:
def suma(*numere):
print(type(numere)) # <class 'tuple'>
total = 0
for n in numere:
total += n
return total
print(suma(1, 2, 3)) # 6
print(suma(1, 2, 3, 4, 5)) # 15
print(suma()) # 0
Combinare cu parametri normali:
def prezinta(titlu, *nume):
print(f"{titlu}:")
for n in nume:
print(f" - {n}")
prezinta("Studenti", "Ana", "Bob", "Cris")
# Studenti:
# - Ana
# - Bob
# - Cris
**kwargs - Argumente Keyword Variabile
**kwargs colecteaza argumente keyword suplimentare intr-un dictionar:
def info(**date):
print(type(date)) # <class 'dict'>
for cheie, valoare in date.items():
print(f"{cheie}: {valoare}")
info(nume="Ana", varsta=20, oras="Cluj")
# nume: Ana
# varsta: 20
# oras: Cluj
Combinare cu alti parametri:
def profil(nume, **detalii):
print(f"Nume: {nume}")
for k, v in detalii.items():
print(f" {k}: {v}")
profil("Ana", varsta=20, job="student")
# Nume: Ana
# varsta: 20
# job: student
Ordinea Parametrilor
Cand combini toate tipurile, ordinea este:
- Parametri pozitionali obligatorii
*args- Parametri keyword-only (dupa
*) **kwargs
def functie(a, b, *args, c=10, **kwargs):
print(f"a={a}, b={b}")
print(f"args={args}")
print(f"c={c}")
print(f"kwargs={kwargs}")
functie(1, 2, 3, 4, c=20, x=30, y=40)
# a=1, b=2
# args=(3, 4)
# c=20
# kwargs={'x': 30, 'y': 40}
Despachetarea Argumentelor
Despachetare lista cu *:
def suma(a, b, c):
return a + b + c
numere = [1, 2, 3]
print(suma(*numere)) # 6 (echivalent cu suma(1, 2, 3))
Despachetare dictionar cu **:
def prezinta(nume, varsta, oras):
print(f"{nume}, {varsta}, {oras}")
date = {"nume": "Ana", "varsta": 20, "oras": "Cluj"}
prezinta(**date) # Ana, 20, Cluj
Parametri Keyword-Only
Parametrii dupa * pot fi transmisi doar ca keyword:
def functie(a, b, *, c, d):
print(a, b, c, d)
# Corect
functie(1, 2, c=3, d=4)
# Gresit
# functie(1, 2, 3, 4) # TypeError
Parametri Positional-Only (Python 3.8+)
Parametrii inainte de / pot fi transmisi doar pozitional:
def functie(a, b, /, c, d):
print(a, b, c, d)
# Corect
functie(1, 2, 3, 4)
functie(1, 2, c=3, d=4)
# Gresit
# functie(a=1, b=2, c=3, d=4) # TypeError
Pattern-uri Comune
Functie cu optiuni multiple:
def conectare(host, port=3306, **optiuni):
print(f"Conectare la {host}:{port}")
for opt, val in optiuni.items():
print(f" {opt}={val}")
conectare("localhost")
conectare("db.server.com", 5432, user="admin", ssl=True)
Wrapper generic:
def log_apel(functie):
def wrapper(*args, **kwargs):
print(f"Apel: {functie.__name__}")
return functie(*args, **kwargs)
return wrapper
Greseli Frecvente
1. Ordinea gresita la apel
def f(a, b):
pass
# f(a=1, 2) # SyntaxError - keyword inainte de positional!
f(1, b=2) # Corect
2. Valoare mutabila ca default
# GRESIT
def f(lista=[]):
lista.append(1)
return lista
# CORECT
def f(lista=None):
if lista is None:
lista = []
lista.append(1)
return lista
3. Confuzie *args si **kwargs
def f(*args, **kwargs):
print(args) # tuple
print(kwargs) # dict
f(1, 2, a=3, b=4)
# (1, 2)
# {'a': 3, 'b': 4}
Puncte Cheie pentru Examen
- Parametri pozitionali: ordinea conteaza
- Parametri keyword: ordinea nu conteaza
- Valori default: parametri obligatorii primii
*args: tuple cu argumente pozitionale extra**kwargs: dict cu argumente keyword extra- NICIODATA lista/dict ca valoare default mutabila!
- Despachetare:
*lista,**dictionar
Intrebari de Verificare
- Care e diferenta intre parametru si argument?
- Ce tip de date este
*args? Dar**kwargs? - De ce nu folosim
lista=[]ca default? - In ce ordine punem parametrii?