course
Abilitățile de programare în Python au devenit din ce în ce mai căutate în ultimii ani. Ca să te ajutăm să îți dezvolți abilitățile de programare în Python, am selectat 30 de trucuri cool în Python pe care le poți folosi pentru a-ți îmbunătăți codul. Încearcă să înveți câte unul în fiecare zi, timp de 30 de zile, și aruncă o privire la articolul nostru despre cele mai bune practici în Python ca să te asiguri că ai un cod de top.
Dacă abilitățile tale de Python nu sunt încă la nivelul dorit, le poți ascuți și cu Python Skill Track.
Trucuri pentru secvențe & structuri de date
#1 Slicing
a = "Hello World!"
print(a[::-1])
"""
!dlroW olleH
"""
Slicing-ul este o funcționalitate în Python care se bazează pe indexare și le permite utilizatorilor să acceseze un subset dintr-o secvență. Un index este pur și simplu poziția unui element într-o secvență. Dacă tipul de secvență este mutabil, poți folosi slicing pentru a extrage și modifica date.
Notă: Putem folosi slicing și pe o secvență imuabilă, dar o încercare de a modifica secțiunea tăiată va genera un TypeError.
Formatul în care este implementat slicing-ul este: sequence[start:stop:step]. Dacă nu sunt specificate valori pentru parametrii start, stop și step, secvența va folosi valorile implicite. Implicitele sunt:
- „start” implicit 0
- „stop” implicit lungimea secvenței
- „step” implicit 1 dacă nu este specificat.
Când folosim sequence[start:stop], elementele returnate vor fi de la indexul de start până la stop - 1 (indexul stop nu este inclus).
Putem trece și indici negativi, care pot fi folosiți pentru a inversa secvența. De exemplu, într-o listă cu 4 elemente, indexul 0 este și indexul -4, iar ultimul index este și -1. În exemplul de cod de mai sus, această logică a fost aplicată parametrului step al secvenței. Drept urmare, șirul a fost afișat invers, începând de la finalul secvenței până la indexul 0.
#2 Swap in-place / atribuire simultană
a = 10
b = 5
print(f"First: {a, b}")
"""
First: (10, 5)
"""
a, b = b, a + 2
print(f"Second: {a, b}")
"""
Second: (5, 12)
"""
Dacă prima ta impresie a fost că valoarea lui b ar fi 7 în loc de 12, ai căzut în capcana swap-ului in-place.
În Python, putem despacheta iterabile în variabile într-o singură atribuire folosind despachetarea automată. De exemplu:
a, b, c = [1, 2, 3]
print(a)
print(b)
print(c)
"""
1
2
3
"""
Putem și colecta mai multe valori într-o singură variabilă folosind * – acest truc în Python se numește „packing”. Mai jos este un exemplu de packing.
a, *b = 1, 2, 3
print(a, b)
"""
1 [2, 3]
"""
Combinarea packing-ului și unpacking-ului automat dă naștere unei tehnici cunoscute drept atribuire simultană. O putem folosi pentru a atribui o serie de valori unei serii de variabile.
#3 Liste vs. tuple-uri
import sys
a = [1, 2, 3, 4, 5]
b = (1, 2, 3, 4, 5)
print(f"List size: {sys.getsizeof(a)} bytes")
print(f"Tuple size: {sys.getsizeof(b)} bytes")
"""
List size: 52 bytes
Tuple size: 40 bytes
"""
Cei mai mulți programatori Python sunt familiari cu structura de date listă. Nu la fel de mulți sunt cu tuple-urile. Ambele sunt iterabile, permit indexarea și stocarea de tipuri eterogene de date. Dar există situații în care folosirea unui tuple poate fi preferată în locul unei liste.
În primul rând, listele sunt mutabile, ceea ce înseamnă că le putem modifica după cum dorim:
a = [1,2,3,4,5]
a[2] = 8
print(a)
"""
[1,2,8,4,5]
"""
Tuple-urile, pe de altă parte, sunt imuabile, ceea ce înseamnă că încercarea de a le modifica va genera un TypeError.
Din acest motiv, tuple-urile sunt mai eficiente din punct de vedere al memoriei, deoarece Python poate aloca exact blocul de memorie necesar datelor. În contrast, pentru o listă trebuie alocată memorie suplimentară în eventualitatea în care o extindem – acest lucru se numește alocare dinamică a memoriei.
Pe scurt: În scenarii în care nu vrei ca datele să fie schimbate, atunci un tuple ar trebui preferat în locul unei liste din motive de memorie. Tuple-urile sunt și mai rapide decât listele.
Află mai multe despre structurile de date în Python în acest tutorial.
#4 Generatoare
a = [x * 2 for x in range(10)]
b = (x * 2 for x in range(10))
print(a)
print(b)
"""
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
<generator object <genexpr> at 0x7f61f8808b50>
"""
List comprehensions sunt maniera „pythonică” de a crea o listă dintr-un alt iterabil – sunt mult mai rapide decât un for loop. Dar ce se întâmplă dacă, din greșeală, schimbi parantezele de la [] la ()? Obții un obiect generator.
În Python, parantezele rotunde cu logica de list comprehension creează ceea ce se numește generator. Generatoarele sunt un tip special de iterabil. Spre deosebire de liste, ele nu își stochează elementele. În schimb, stochează instrucțiuni pentru a genera pe rând fiecare element și starea curentă a iterărilor.
Fiecare element este generat doar la cerere folosind o tehnică numită evaluare leneșă (lazy). Principalul avantaj al acestui truc cu generatorul este că folosește mai puțină memorie, deoarece întreaga secvență nu este construită deodată.
#5 Alias-uri
a = [1, 2, 3, 4 ,5]
b = a
# Change the 4th index in b
b[4] = 7
print(id(a))
print(id(b))
print(a) # Remember we did not explicitly make changes to a.
"""
15136008
15136008
[1, 2, 3, 4, 7]
"""
Python este un limbaj orientat pe obiecte – totul este un obiect. Așadar, atribuirea unui obiect unui identificator înseamnă crearea unei referințe către acel obiect.
Când atribuim un identificator altui identificator, ajungem cu doi identificatori care fac referire la același obiect. Acest concept se numește aliasing. Schimbările într-un alias îl vor afecta pe celălalt. Uneori acest comportament este dorit, dar adesea ne ia prin surprindere.
O soluție este să eviți aliasing-ul când folosești obiecte mutabile. O altă soluție ar fi să creezi un clonă a obiectului original în loc de o referință.
Cel mai simplu mod de a crea o clonă este folosind slicing:
b = a[:]
Asta va crea o nouă referință către un obiect listă în identificatorul b.
Poți găsi și alte soluții, precum apelarea list(a) când atribui datele altui identificator sau folosirea metodei copy().
#6 Operatorul „not”
a = []
print(not a)
"""
True
"""
Următorul nostru truc Python este cea mai simplă modalitate de a verifica dacă structura ta de date e goală: folosește operatorul not. not este un operator logic încorporat în Python care returnează True dacă expresia nu este adevărată, altfel returnează False – inversează valoarea de adevăr a expresiilor și obiectelor booleene.
O altă manieră în care îl poți vedea folosit este într-o instrucțiune if:
if not a:
# do something...
Când a este True, operatorul not va returna False și invers.
Poate fi greu de înțeles la început, așa că încearcă-l.
Trucuri pentru șiruri și output
#7 F-strings
first_name = "John"
age = 19
print(f"Hi, I'm {first_name} and I'm {age} years old!")
"""
Hi, I'm John and I'm 19 years old!
"""
Din când în când, e posibil să avem nevoie să formatam un șir; Python 3.6 a introdus o funcționalitate cool numită f-strings pentru a simplifica acest proces. Ajută să înțelegi cum erau formatare șirurile înainte de noua versiune ca să apreciezi mai bine metoda nouă.
Iată cum se formatau șirurile înainte:
first_name = "John"
age = 19
print("Hi, I'm {} and I'm {} years old!".format(first_name, age))
"""
Hi, I'm John and I'm 19 years old!
"""
În esență, noul mod de formatare este mai rapid, mai lizibil, mai concis și mai greu de greșit.
Un alt folos al f-strings este să afișezi numele unui identificator împreună cu valoarea. Acest lucru a fost introdus în Python 3.8.
x = 10
y = 20
print(f"{x = }, {y = }")
"""
x = 10, y = 20
"""
Vezi acest tutorial despre Formatarea cu f-strings în Python pentru a afla mai multe.
#8 Parametrul „end” al funcției print()
languages = ["english", "french", "spanish", "german", "twi"]
print(' '.join(languages))
"""
english french spanish german twi
"""
Este destul de comun să folosim o instrucțiune print fără a defini vreunul dintre parametrii opționali. Drept urmare, mulți Pythoniști nu știu că poți controla într-o anumită măsură output-ul.
Un parametru opțional pe care îl putem modifica este end. Parametrul end specifică ce ar trebui afișat la finalul unui apel la print.
Valoarea implicită a lui end este "\n", care îi spune lui Python să înceapă o linie nouă. În codul de mai sus, am schimbat-o într-un spațiu. Astfel, output-ul a afișat toate elementele listei pe aceeași linie.
#9 Adăugare într-un tuple
a = (1, 2, [1, 2, 3])
a[2].append(4)
print(a)
"""
(1, 2, [1, 2, 3, 4])
"""
Știm deja că tuple-urile sunt imuabile – vezi trucul Python #3 Liste vs. Tuple-uri. Încercarea de a schimba starea unui tuple ar arunca un TypeError. Dar, dacă te gândești la un tuple ca la o secvență de nume cu legături către obiecte care nu pot fi schimbate, s-ar putea să vezi lucrurile altfel.
Primele două elemente ale tuple-ului nostru sunt întregi – sunt imuabile. Ultimul element este o listă, un obiect mutabil în Python.
Dacă privim lista ca pe încă un nume dintr-o secvență cu o legătură către un obiect ce nu poate fi schimbată, ne dăm seama că lista poate fi totuși modificată din interiorul tuple-ului.
Am recomanda să faci asta în practică? Probabil nu, dar e unul dintre acele lucruri bune de știut!
#10 Îmbinarea dicționarelor
a = {"a": 1, "b": 2}
b = {"c": 3, "d": 4}
a_and_b = a | b
print(a_and_b)
"""
{"a": 1, "b": 2, "c": 3, "d": 4}
"""
În Python 3.9 și versiunile ulterioare, este posibil să îmbini dicționare folosind | (OR pe biți). Nu e mult de spus despre acest truc, decât că este o soluție mult mai lizibilă!
Trucuri de stil de cod & sintaxă
#11 Operator ternar / expresii condiționale
condition = True
name = "John" if condition else "Doe"
print(name)
"""
John
"""
În codul de mai sus, vezi ceea ce se numește operator ternar – mai este numit și expresie condițională. Folosim operatorii ternari pentru a evalua lucruri în funcție de faptul că o condiție este True sau False.
O altă modalitate de a scrie codul de mai sus ar fi astfel:
condition = True
if condition:
name = "John"
else:
name = "Doe"
print(name)
"""
John
"""
Deși ambele variante produc același rezultat, observă cum condiționala ternară ne permite să scriem un cod mult mai scurt și mai clar. Este ceea ce Pythoniștii ar numi modul mai „pythonic” de a scrie cod.
#12 Eliminarea duplicatelor din liste
a = [1, 1, 2, 3, 4, 5, 5, 5, 6, 7, 2, 2]
print(list(set(a)))
"""
[1, 2, 3, 4, 5, 6, 7]
"""
Cel mai simplu mod de a elimina elementele duplicate dintr-o listă este să convertești lista într-un set (și apoi înapoi într-o listă, dacă vrei).
Din punctul de vedere al mutabilității, set-urile și listele sunt destul de asemănătoare în Python. Putem adăuga și elimina elemente din ambele structuri de date după bunul plac, dar tot sunt extrem de diferite.
Listele sunt ordonate, indexate de la zero și mutabile. Set-urile sunt neordonate și neindexate. Elementele dintr-un set trebuie să fie de tip imuabil, chiar dacă set-ul în sine este mutabile – încercarea de a accesa un element prin index sau de a modifica un element va genera o eroare.
O altă diferență cheie între set-uri și liste este că set-urile nu pot conține duplicate. Asta ne-a ajutat să eliminăm elementele duplicate din listă.
#13 Liniuța jos solitară
>>> print(_)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
>>> 1 + 2
3
>>> print(_)
3
Caracterul underscore (_) este un identificator valid în Python, deci îl poți folosi pentru a referenția un obiect. Dar underscore are și o altă responsabilitate: să stocheze rezultatul ultimei evaluări.
Documentația spune că „interpretorul interactiv face rezultatul ultimei evaluări disponibil în variabila _. (Este stocat în modulul builtins, alături de funcțiile încorporate precum print).”
Deoarece nu am atribuit underscore-ului un obiect înainte de a-l apela pe prima linie, am primit o eroare. Totuși, când am calculat rezultatul lui 1 + 2, interpretorul interactiv a stocat rezultatul în identificatorul _ pentru noi.
#14 Underscore pentru a ignora valori
for _ in range(100):
print("The index doesn't matter")
"""
The index doesn't matter
The index doesn't matter
...
"""
În trucul #13 am văzut că interpretorul interactiv face disponibil în identificatorul (_) ultimul rezultat al unei evaluări, dar acesta nu este singurul caz de utilizare.
Îl putem folosi și pentru a reprezenta obiecte de care nu ne pasă sau pe care nu le vom folosi mai târziu în program. Acest lucru este important deoarece folosirea unui identificator în loc de underscore (_) va ridica o eroare F841 când rulăm un linter pe program. O eroare F841 indică faptul că unei variabile locale i s-a atribuit un nume, dar nu a fost folosită în program, ceea ce este o practică proastă.
#15 Underscore final
list_ = [0, 1, 2, 3, 4]
global_ = "Hi there"
Continuând din ultimele două trucuri legate de folosirea underscore-ului (_), un alt scop este evitarea conflictelor cu cuvintele cheie Python.
PEP 8 menționează că un underscore final (_) ar trebui „folosit prin convenție pentru a evita conflictele cu cuvinte cheie Python.” De asemenea, afirmă că „în general este mai bine să adaugi un singur underscore final decât să folosești o abreviere sau o corupere a scrierii. Astfel, list_ e mai bun decât lst.”
#16 Underscore inițial
class Example:
def __init__(self):
self._internal = 2
self.external = 20
Vei observa adesea că programatorii Python experimentați prefixează un underscore unui identificator sau nume de metodă – și pe bună dreptate.
Underscore-ul prefixat unui identificator sau unei metode are un înțeles ascuns: această variabilă sau metodă este destinată doar uzului intern. Practic, este un avertisment pentru alți programatori, definit în PEP 8, dar care nu este impus de Python. Prin urmare, underscores inițiale sunt un indicator slab.
Spre deosebire de Java, Python nu are o distincție puternică între variabile private și publice. Cu alte cuvinte, are sens doar pentru că comunitatea Python a căzut de acord asupra acestui sens. Includerea lor nu influențează comportamentul programelor tale.
#17 Underscore ca separator vizual
Iată ultimul sfat despre underscores; până acum am acoperit trei cazuri de utilizare, dar poți consulta tutorialul nostru pentru a afla mai multe despre Rolul underscore-ului (_) în Python.
number = 1_500_000
print(number)
"""
15000000
"""
O altă utilizare a underscore-ului este ca separator vizual pentru gruparea cifrelor în literali întregi, în virgulă mobilă și complecși – a fost introdusă în Python 3.6.
Ideea a fost să ajute lizibilitatea literalilor lungi sau a celor a căror valoare ar trebui clar separată în părți – poți citi mai multe în PEP 515.
Trucuri de stil de cod & sintaxă
#18 __name__ == „__main__”
if __name__ == "__main__":
print("Read on to understand what is going on when you do this.")
"""
print("Read on to understand what is going on when you do this.")
"""
Este foarte probabil să fi văzut această sintaxă în mai multe programe Python; Python folosește un nume special numit "__main__" și îl setează în identificatorul __name__ dacă fișierul Python rulat este programul principal.
Dacă decidem să importăm modulul afișat în captura de ecran într-un alt modul (fișier Python) și rulăm acel fișier, expresia din codul nostru va fi falsă. Asta pentru că, atunci când importăm din alt modul, identificatorul __name__ este setat la numele modulului (fișierului Python).
#19 Metoda „setdefault”
import pprint
text = "It's the first of April. It's still cold in the UK. But I'm going to the museum so it should be a wonderful day"
counts = {}
for word in text.split():
counts.setdefault(word, 0)
counts[word] += 1
pprint.pprint(counts)
"""
{'April.': 1,
'But': 1,
"I'm": 1,
"It's": 2,
'UK.': 1,
'a': 1,
'be': 1,
'cold': 1,
'day': 1,
'first': 1,
'going': 1,
'in': 1,
'it': 1,
'museum': 1,
'of': 1,
'should': 1,
'so': 1,
'still': 1,
'the': 3,
'to': 1,
'wonderful': 1}
"""
S-ar putea să vrei să setezi o valoare pentru diverse chei într-un dicționar. De exemplu, când urmărești numărul de apariții ale cuvintelor într-un corpus. Modul obișnuit este următorul:
- Verifici dacă cheia există în dicționar
- Dacă există, incrementezi valoarea cu 1.
- Dacă nu există, o adaugi și setezi valoarea la 1.
Așa arată în cod:
counts = {}
for word in text.split():
if word in counts:
counts[word] += 1
else:
counts[word] = 1
O modalitate mai concisă este să folosești metoda setdefault() pe obiectul tău dicționar.
Primul argument transmis metodei este cheia pe care vrem să o verificăm. Al doilea argument este valoarea la care setăm cheia dacă aceasta nu există deja în dicționar – dacă cheia există, metoda va returna valoarea cheii. Astfel, nu va fi schimbată.
Trucuri de structură a programului
#20 Potrivire cu regex
import re
number = re.compile(r"(0)?(\+44)?\d{10}")
num_1 = number.search("My number is +447999999999")
num_2 = number.search("My number is 07999999999")
print(num_1.group())
print(num_2.group())
"""
'+447999999999'
'07999999999'
"""
Expresiile regulate îți permit să specifici un tipar de text de căutat; Majoritatea oamenilor știu că putem căuta lucruri folosind CTRL + F (Windows), dar dacă nu știi exact ce cauți, cum l-ai găsi? Răspunsul este să cauți tipare.
De exemplu, numerele din Marea Britanie urmează un tipar similar: vor avea un zero la început plus zece cifre sau +44 în loc de zero și zece cifre – a doua variantă indică formatul internațional.
Expresiile regulate economisesc mult timp. Dacă am scrie reguli ca să prindem cazurile din imaginea noastră în loc de regex, ne-ar putea lua peste 10 linii de cod.
Învață cum funcționează expresiile regulate chiar dacă nu scrii cod. Majoritatea editorilor de text și procesatoarelor moderne îți permit să folosești regex pentru funcțiile de găsire și înlocuire.
#21 Pipe în regex
import re
heros = re.compile(r"Super(man|woman|human)")
h1 = heros.search("This will find Superman")
h2 = heros.search("This will find Superwoman")
h3 = heros.search("This will find Superhuman")
print(h1.group())
print(h2.group())
print(h3.group())
"""
Superman
Superwoman
Superhuman
"""
Expresiile regulate au un caracter special numit pipe (|) care îți permite să potrivești una dintre mai multe expresii și poate fi folosit oriunde. Este super util când ai mai multe tipare similare.
De exemplu, „Superman”, „Superwoman” și „Superhuman” au același prefix. Astfel, poți folosi pipe pentru a păstra partea recurentă a tiparului și a schimba părțile care diferă. Din nou, îți economisește timp prețios.
Atenție la capcană: dacă toate expresiile pe care vrei să le potrivești apar în același text, va fi returnată prima apariție – de ex., „An example text containing Superwoman, Superman, Superhuman” va returna Superwoman.
#22 Parametrul „sep” al funcției print()
day = "04"
month = "10"
year = "2022"
print(day, month, year)
print(day, month, year, sep = "")
print(day, month, year, sep = ".")
"""
04 10 2022
04/10/2022
04.10.2022
"""
Numărul programatorilor Python care nu cunosc capabilitățile complete ale funcției print() este surprinzător; Dacă „Hello World” a fost primul tău program, print() a fost probabil una dintre primele funcții încorporate pe care le-ai învățat. Folosim print() pentru a afișa mesaje formate pe ecran, dar funcția print() poate face mult mai mult.
În codul de mai sus, am arătat diferite moduri de a afișa mesajul formatat. Parametrul sep este un argument opțional în funcția print() care ne permite să specificăm cum ar trebui separate obiectele dacă includem mai multe.
Implicit, ele sunt separate printr-un spațiu, dar am schimbat acest comportament în instrucțiunile noastre print – una unde sep este setat la "" și alta unde sep este setat la ".".
#23 Funcții lambda
def square(num:int) -> int:
return num ** 2
print(f"Function call: {square(4)}")
"""
Function call: 16
"""
square_lambda = lambda x: x**2
print(f"Lambda function: {square_lambda(4)}")
"""
Lambda functional: 16
"""
Funcțiile lambda te duc spre nivelul intermediar-avansat al lucrurilor pe care le poți face în Python – învață Python intermediar cu acest curs. Par complicate la prima vedere, dar sunt destul de simple.
În exemplul nostru am folosit un singur argument, dar am fi putut folosi mai multe, dacă am fi vrut:
square = lambda a, b: a ** b
print(f"Lambda function: {square(4, 2)}")
"""
16
"""
În esență, cuvântul cheie lambda ne permite să creăm funcții mici, restrânse, anonime, într-o singură linie. Se comportă ca o funcție obișnuită declarată cu def, cu excepția faptului că aceste funcții nu au nume.
#24 Metoda „swapcase”
string = "SoMe RaNDoM sTriNg"
print(string.swapcase())
"""
sOmE rAndOm StRInG
"""
Metoda swapcase() se aplică unui șir pentru a transforma literele mari în mici și invers, într-o singură linie de cod. Nu sunt multe cazuri de utilizare pentru swapcase(), dar e bine de știut.
#25 Metoda „isalnum”
password = "ABCabc123"
print(password.isalnum())
"""
True
"""
Să zicem că facem un program care cere utilizatorilor să introducă o parolă, dar aceasta trebuie să aibă o combinație de cifre și litere. Putem face asta într-o singură linie apelând isalnum() pe instanța de șir.
Metoda verifică dacă toate caracterele sunt litere (A-Za-z) sau cifre (0-9). Un spațiu sau un simbol (!#%$&? etc.) va returna False.
#26 Gestionarea excepțiilor
def get_ration(x:int, y:int) -> int:
try:
ratio = x/y
except ZeroDivisionError:
y = y + 1
ratio = x/y
return ratio
print(get_ration(x=400, y=0))
"""
400.0
"""
Programele Python se opresc atunci când întâlnesc o eroare.
Uneori nu vrem acest comportament, de exemplu când un utilizator final interacționează cu codul nostru. Cât de rău ar fi dacă programul nostru s-ar închide prematur într-o astfel de situație?
Există câteva curente de gândire despre cum să tratezi cazurile excepționale. Majoritatea programatorilor Python îmbrățișează ideea că e mai ușor să cere iertare decât permisiune. Asta înseamnă că preferă să prindă o eroare ridicată oferind context în jur capabil să gestioneze excepția. Ideea din spate este că nu are rost să pierzi timp încercând să te protejezi împotriva tuturor cazurilor excepționale posibile.
Dar asta e valabil doar când există un mecanism pentru a face față problemei după ce apare.
#27 Identificarea diferențelor dintre liste
list_1 = [1, 3, 5, 7, 8]
list_2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
solution_1 = list(set(list_2) - set(list_1))
solution_2 = list(set(list_1) ^ set(list_2))
solution_3 = list(set(list_1).symmetric_difference(set(list_2)))
print(f"Solution 1: {solution_1}")
print(f"Solution 2: {solution_2}")
print(f"Solution 3: {solution_3}")
"""
Solution 1: [9, 2, 4, 6]
Solution 2: [2, 4, 6, 9]
Solution 3: [2, 4, 6, 9]
"""
Iată trei metode diferite de a compara diferența dintre două liste în Python.
Notă: Cu excepția cazului în care știi sigur că list_1 este un subset al lui list_2, soluția 1 nu este aceeași cu celelalte două.
#28 Args & kwargs
def some_function(*args, **kwargs):
print(f"Args: {args}")
print(f"Kwargs: {kwargs}")
some_function(1, 2, 3, a=4, b=5, c=6)
"""
Args: (1, 2, 3)
Kwargs: {'a': 4, 'b': 5, 'c': 6}
"""
Folosim *args și **kwargs ca parametri ai unei funcții când nu știm câte variabile ar trebui să aștepte funcția noastră.
Parametrul *args ne permite să trecem un număr variabil de parametri către o funcție atunci când nu sunt cuvinte cheie (adică parametrii nu necesită un nume asociat). Pe de altă parte, the **kwargs parametrul ne permite să trecem un număr arbitrar de parametri cu nume către o funcție.
De fapt, cuvintele *args și **kwargs nu sunt ele însele magice: magia e în asteriscuri (*). Asta înseamnă că am fi putut folosi orice cuvânt după asteriscuri, dar folosirea lui args și kwargs este practică comună, adoptată de dezvoltatorii Python.
#29 Ellipsis
print(...)
"""
Ellipsis
"""
def some_function():
...
# Alternative solution
def another_function():
pass
Ellipsis este un obiect Python care poate fi apelat fie printr-o secvență de trei puncte (...), fie prin apelarea obiectului însuși (Ellipsis).
Cea mai notabilă utilizare este pentru accesarea și slicing-ul array-urilor multidimensionale în NumPy, de exemplu:
import numpy as np
arr = np.array([[2,3], [1,2], [9,8]])
print(arr[...,0])
"""
[2 1 9]
"""
print(arr[...])
"""
[[2 3]
[1 2]
[9 8]]
"""
Dar o altă utilizare a lui Ellipsis este ca placeholder într-o funcție neimplementată.
Adică poți pune Ellipsis, ... sau pass, și toate vor fi valide.
#30 List comprehension
even_numbers = [x for x in range(10) if x % 2 == 0 and x != 0]
print(even_numbers)
"""
[2, 4, 6, 8]
"""
Ultimul nostru truc Python este list comprehension, o modalitate elegantă de a crea o listă dintr-o altă secvență. Îți permit să aplici logică și filtrare sofisticată, așa cum am făcut în codul de mai sus.
Există și alte modalități de a obține același obiectiv; de exemplu, am fi putut folosi o funcție lambda astfel:
even_numbers = list(filter(lambda x: x % 2 ==0 and x != 0, range(10)))
print(even_numbers)
"""
[0, 2, 4, 6, 8]
"""
Dar mulți Pythoniști ar argumenta că această soluție este mult mai puțin lizibilă decât list comprehension.
Întrebări frecvente
Care este cel mai util truc Python pentru începători?
F-strings sunt probabil cele mai utile pe loc. Fac formatarea șirurilor mai rapidă, mai lizibilă și mai greu de greșit comparativ cu abordări mai vechi precum .format().
Care este cea mai rapidă metodă de a inversa două variabile în Python?
Folosește atribuirea simultană: a, b = b, a. Nu e nevoie de variabilă temporară — Python evaluează complet partea din dreapta înainte de atribuire.
Cum îmbin două dicționare într-o singură linie?
În Python 3.9+, folosește operatorul |: merged = dict_a | dict_b. Pentru versiuni mai vechi, folosește {**dict_a, **dict_b}.
Care este diferența dintre *args și **kwargs?
*args colectează argumentele poziționale suplimentare într-un tuple. **kwargs colectează argumentele cu nume suplimentare într-un dicționar. Magia stă în operatorii * și **, nu în cuvintele în sine — le-ai putea numi oricum.
Cum verific dacă o listă este goală în Python?
Folosește operatorul not: if not my_list:. Este mai „pythonic” decât să verifici len(my_list) == 0.
Care este diferența dintre o list comprehension și un generator?
O list comprehension (paranteze pătrate) construiește întreaga listă în memorie dintr-odată. Un generator (paranteze rotunde) produce valorile pe rând, la cerere, folosind mult mai puțină memorie pentru secvențe mari.
Când ar trebui să folosesc un operator ternar?
Folosește-l pentru condiționale simple, într-o linie, unde ambele rezultate sunt scurte și clare: name = "John" if condition else "Doe". Pentru ceva mai complex, un bloc obișnuit if/else este mai lizibil.
Care este cea mai ușoară metodă de a elimina duplicatele dintr-o listă?
Înfășoar-o într-un set() și convertește înapoi: list(set(my_list)). Ține cont că set-urile sunt neordonate, deci ordinea originală nu va fi păstrată.