🐍

Parametri si Argumente

Programare Python Intermediar 1 min citire 0 cuvinte

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:

  1. Parametri pozitionali obligatorii
  2. *args
  3. Parametri keyword-only (dupa *)
  4. **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

  1. Care e diferenta intre parametru si argument?
  2. Ce tip de date este *args? Dar **kwargs?
  3. De ce nu folosim lista=[] ca default?
  4. In ce ordine punem parametrii?

📚 Articole Corelate