Cum să utilizați operatorii de despachetare (*, **) în Python?
Publicat: 2021-07-02Python este cel mai folosit limbaj de programare. Astăzi veți învăța să utilizați una dintre caracteristicile sale de bază, dar adesea ignorate, despachetarea în Python.
Probabil ați văzut * și ** în codul altora sau chiar le-ați folosit fără să știți care este scopul lor. Vom parcurge conceptul de despachetare și cum să îl folosim pentru a scrie mai mult cod Pythonic.
Iată o listă de concepte pe care le veți găsi utile în timp ce citiți acest tutorial:
- Iterabil : orice secvență care poate fi iterată printr-o buclă for , cum ar fi seturi, liste, tupluri și dicționare
- Apelabil : un obiect Python care poate fi apelat folosind paranteze duble (), de exemplu, funcția mea()
- Shell: mediu de rulare interactiv care ne permite să rulăm cod Python. Îl putem numi rulând „python” într-un terminal
- Variabilă: Nume simbolic care stochează un obiect și are o locație de memorie rezervată.
Să începem cu cea mai frecventă confuzie: Asteristicile în Python sunt și operatori aritmetici. Un asterisc (*) este folosit pentru înmulțire, în timp ce două dintre ele (**) se referă la exponențiere.
Putem demonstra că deschizând un shell Python și tastând:
>>> 3*3 9 >>> 3**3 27Notă: Trebuie să aveți instalat Python 3 pentru a urma acest tutorial. Dacă nu îl aveți instalat, consultați ghidul nostru de instalare Python.
După cum puteți vedea, folosim asteriscul după primul număr și înainte de al doilea. Când vedeți asta, înseamnă că folosim operatorii aritmetici.
Pe de altă parte, folosim asteriscurile (*, **) înaintea unui iterabil pentru a-l despacheta - de exemplu:
>>> *range(1, 6), (1, 2, 3, 4, 5) >>> {**{'vanilla':3, 'chocolate':2}, 'strawberry':2} {'vanilla': 3, 'chocolate': 2, 'strawberry': 2}Nu vă faceți griji dacă nu îl primiți, acesta este doar un preambul pentru despachetarea în Python. Așa că mergeți mai departe și citiți întregul tutorial!
Ce despachetează?
Dezambalarea este procesul de a scoate lucruri — iterabile, cum ar fi liste, tupluri și dicționare. Gândiți-vă la asta ca la deschiderea unei cutii și la scoaterea diferitelor articole precum cabluri, căști sau un USB.

Să traducem același exemplu în cod pentru o mai bună înțelegere:
>>> mybox = ['cables', 'headphones', 'USB'] >>> item1, item2, item3 = myboxDupă cum puteți vedea, atribuim cele trei elemente din lista mybox la trei variabile item1, item2, item2 . Acest tip de atribuire a variabilelor este conceptul fundamental de despachetare în Python.
Dacă încercați să obțineți valoarea fiecărui element, veți observa că item1, se referă la „cabluri“, ITEM2, se referă la „căști“ și așa mai departe.
>>> item1 'cables' >>> item2 'headphones' >>> item3 'USB'Până aici, totul pare să fie în regulă cu acest cod, dar dacă am dori să despachetăm o listă cu mai multe elemente în ea - păstrând aceeași cantitate de variabile alocate?
>>> newbox = ['cables', 'headphones', 'USB', 'mouse'] >>> item1, item2, item3 = newbox Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: too many values to unpack (expected 3)Probabil te așteptai la acest tip de eroare. În esență, atribuim 4 elemente de listă la trei variabile, cum reușește Python să atribuie valorile potrivite?
Nu, asta pentru că primim o ValueError cu mesajul „prea multe valori de despachetat”. Acest lucru se întâmplă deoarece setăm trei variabile în stânga și patru valori (corespunzând listei newbox) în dreapta.
Dacă încercați să faceți un proces similar, dar cu mai multe variabile decât valori de despachetat, veți primi o altă ValueError, cu excepția faptului că cu un mesaj ușor diferit:
>>> lastbox = ['cables', 'headphones'] >>> item1, item2, item3 = lastbox Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: not enough values to unpack (expected 3, got 2)Notă: am lucrat cu liste, dar puteți folosi această formă de despachetare cu orice iterabil (liste, seturi, tupluri, dicționare)
Deci cum depășim această situație? Există vreo modalitate de a despacheta toate elementele unui iterabil la câteva variabile fără a primi erori?
Sigur că există și se numește operator de despachetare sau operator de asterisc (*, **). Să vedem cum să-l folosești în Python.
Cum să despachetezi liste cu operatorul *
Operatorul asterisc (*) este folosit pentru a despacheta toate valorile unui iterabil care nu au fost încă atribuite.
Să presupunem că doriți să obțineți primul și ultimul element al unei liste fără a utiliza indecși, am putea face acest lucru cu operatorul asterisc:
>>> first, *unused, last = [1, 2, 3, 5, 7] >>> first 1 >>> last 7 >>> unused [2, 3, 5]După cum puteți aprecia, obținem toate valorile neutilizate cu operatorul asterisc. Modul preferat de a renunța la valori este folosirea unei variabile de subliniere (_), care este uneori folosită ca „variabilă inactivă”.
>>> first, *_, last = [1, 2, 3, 5, 7] >>> _ [2, 3, 5]Putem folosi în continuare acest truc chiar dacă lista are doar două elemente:
>>> first, *_, last = [1, 2] >>> first 1 >>> last 2 >>> _ []În acest caz, variabila de subliniere (variabilă inactivă) stochează o listă goală, astfel încât celelalte două variabile din jurul lor să poată accesa valorile disponibile ale listei.
Depanare comună
Putem despacheta un element unic al unui iterabil. De exemplu, ai veni cu ceva de genul acesta:
>>> *string = 'PythonIsTheBest'Cu toate acestea, codul de mai sus va returna o SyntaxError :
>>> *string = 'PythonIsTheBest' File "<stdin>", line 1 SyntaxError: starred assignment target must be in a list or tupleAceasta deoarece, conform specificației PEP:
Un tuplu (sau listă) în partea stângă a unei sarcini simple
Dacă vrem să despachetăm toate valorile unui iterabil într-o singură variabilă, trebuie să setăm un tuplu, prin urmare adăugarea unei simple virgule va fi suficientă:
>>> *string, = 'PythonIsTheBest' >>> string ['P', 'y', 't', 'h', 'o', 'n', 'I', 's', 'T', 'h', 'e', 'B', 'e', 's', 't']Un alt exemplu ar fi folosirea funcției interval , care returnează o secvență de numere.

>>> *numbers, = range(5) >>> numbers [0, 1, 2, 3, 4]Acum că știți cum să despachetați liste și tupluri cu un asterisc, este timpul să intrați în despachetarea dicționarelor.
Cum să despachetezi dicționare cu operatorul **
În timp ce un singur asterisc este folosit pentru a despacheta liste și tupluri, asteriscul dublu (**) este folosit pentru a despacheta dicționare.
Din păcate, nu putem despacheta un dicționar într-o singură variabilă, așa cum am procedat cu tupluri și liste. Aceasta înseamnă că următoarele vor genera o eroare:
>>> **greetings, = {'hello': 'HELLO', 'bye':'BYE'} ... SyntaxError: invalid syntaxCu toate acestea, putem folosi operatorul ** în interiorul apelabilelor și al altor dicționare. De exemplu, dacă dorim să creăm un dicționar îmbinat, realizat din alte dicționare, am putea folosi codul de mai jos:
>>> food = {'fish':3, 'meat':5, 'pasta':9} >>> colors = {'red': 'intensity', 'yellow':'happiness'} >>> merged_dict = {**food, **colors} >>> merged_dict {'fish': 3, 'meat': 5, 'pasta': 9, 'red': 'intensity', 'yellow': 'happiness'}Aceasta este o modalitate destul de scurtă de a crea dicționare compuse, cu toate acestea, aceasta nu este abordarea principală a dezambalării în Python.
Să vedem cum putem folosi despachetarea cu apelabile
Ambalare în Funcții: args și kwargs
Probabil ați văzut args și kwargs înainte fie implementate pe clase sau funcții. Să vedem de ce trebuie să le folosim împreună cu apelabile.
Împachetare cu operatorul * (args)
Să presupunem că avem o funcție care calculează produsul a două numere.
>>> def product(n1, n2): ... return n1 * n2 ... >>> numbers = [12, 1] >>> product(*numbers) 12După cum puteți vedea, despachetăm numerele listei în funcție, așa că rulăm de fapt următoarele:
>>> product(12, 1) 12Până aici, totul merge bine, dar dacă am vrea să trecem pe o listă mai lungă? Cu siguranță va genera o eroare, deoarece funcția primește mai multe argumente decât este capabilă să gestioneze.
>>> numbers = [12, 1, 3, 4] >>> product(*numbers) ... TypeError: product() takes 2 positional arguments but 4 were givenPutem rezolva toate acestea doar împachetând lista direct pe funcție, ceea ce creează un iterabil în interiorul acesteia și ne permite să transmitem orice număr de argumente funcției.
>>> def product(*args): ... result = 1 ... for i in args: ... result *= i ... return result ... >>> product(*numbers) 144Aici tratăm parametrul args ca pe un iterabil, parcurgând elementele sale și returnând produsul tuturor numerelor. Observați cum numărul de pornire al rezultatului trebuie să fie unul, deoarece dacă începem cu zero, funcția va returna întotdeauna zero.
Notă: args este doar o convenție, puteți utiliza orice alt nume de parametru
De asemenea, am putea trece numere arbitrare funcției fără a folosi o listă, la fel ca în cazul funcției de imprimare încorporată.
>>> product(5, 5, 5) 125 >>> print(5, 5, 5) 5 5 5În cele din urmă, să obținem tipul de obiect al argumentelor unei funcții.
>>> def test_type(*args): ... print(type(args)) ... print(args) ... >>> test_type(1, 2, 4, 'a string') <class 'tuple'> (1, 2, 4, 'a string')După cum s-a menționat în codul de mai sus, tipul de argumente va fi întotdeauna tuple , iar conținutul acestuia va fi toate argumentele fără cuvinte cheie transmise funcției.
Ambalare cu operatorul ** (kwargs)
După cum am văzut anterior, operatorul ** este folosit exclusiv pentru dicționare. Aceasta înseamnă că cu acest operator putem să transmitem perechi cheie-valoare funcției ca parametru.
Să creăm o funcție make_person , care primește un argument pozițional „nume” și o cantitate nedefinită de argumente cu cuvinte cheie.
>>> def make_person(name, **kwargs): ... result = name + ': ' ... for key, value in kwargs.items(): ... result += f'{key} = {value}, ' ... return result ... >>> make_person('Melissa', id=12112, location='london', net_worth=12000) 'Melissa: id = 12112, location = london, net_worth = 12000, 'După cum puteți vedea, instrucțiunea **kwargs convertește toate argumentele cu cuvinte cheie într-un dicționar, pe care îl putem itera în interiorul funcției.
Notă: kwargs este doar o convenție pe care o puteți numi acest parametru cu orice doriți
Putem verifica tipul kwarg - urilor în același mod în care am făcut-o cu args :
>>> def test_kwargs(**kwargs): ... print(type(kwargs)) ... print(kwargs) ... >>> test_kwargs(random=12, parameters=21) <class 'dict'> {'random': 12, 'parameters': 21}Variabila internă kwargs se transformă întotdeauna într-un dicționar, care stochează perechile cheie-valoare transmise funcției.
În cele din urmă, să folosim args și kwargs în aceeași funcție:
>>> def my_final_function(*args, **kwargs): ... print('Type args: ', type(args)) ... print('args: ', args) ... print('Type kwargs: ', type(kwargs)) ... print('kwargs: ', kwargs) ... >>> my_final_function('Python', 'The', 'Best', language='Python', users='A lot') Type args: <class 'tuple'> args: ('Python', 'The', 'Best') Type kwargs: <class 'dict'> kwargs: {'language': 'Python', 'users': 'A lot'}Concluzie
Operatorii de despachetare sunt cu adevărat utili în sarcinile de zi cu zi, acum știi cum să-i folosești atât în declarații individuale, cât și în parametrii funcției.
În acest tutorial ați învățat:
- Folosiți * pentru tupluri și liste și ** pentru dicționare
- Puteți utiliza operatori de despachetare în constructorii de funcții și clase
- arg-urile sunt folosite pentru a transmite funcțiilor parametri care nu sunt formulați cu cheie
- kwargs sunt folosite pentru a transmite parametrii cu cuvinte cheie la funcții.
