Diferența dintre zip(list) și zip(*list) [duplicat] (Programare, Python, Python 3.X)

user3735438 a intrebat.

Folosesc o listă p = [[1,2,3],[4,5,6]]

Dacă fac :

>>>d=zip(p)
>>>list(d)
[([1, 2, 3],), ([4, 5, 6],)]

Deși, ceea ce vreau eu de fapt se obține folosind acest lucru:

>>>d=zip(*p)
>>>list(d)
[(1, 4), (2, 5), (3, 6)]

Am descoperit că adăugarea unui „*” înaintea numelui listei îmi dă rezultatul dorit, dar nu pot să îmi dau seama care este diferența în funcționarea lor. Puteți explica, vă rog, care este diferența?

6 răspunsuri
Sneftel

zip dorește ca o grămadă de argumente să se comprime împreună, dar ceea ce ai tu este un singur argument (o listă, ale cărei elemente sunt tot liste). La * dintr-un apel de funcție „descompactează” o listă (sau alt iterabil), făcând din fiecare dintre elementele sale un argument separat. Așadar, fără *, , faceți zip( [[1,2,3],[4,5,6]] ). Cu *, , faceți zip([1,2,3], [4,5,6]).

Comentarii

  • cea mai bună explicație pe care am citit-o vreodată despre operatorul unpack *. Vă mulțumesc. –  > Por Antoine Colson.
Noufal Ibrahim

The * descompune argumentele dintr-o instrucțiune de invocare a unei funcții.

Luați în considerare acest lucru

def add(x, y):
   return x + y

dacă aveți o listă t = [1,2], , puteți spune fie add(t[0], t[1]) ceea ce este inutil de verbos sau puteți „despacheta” t în argumente separate folosind operatorul * operator, astfel add(*t).

Aceasta este ceea ce se întâmplă în exemplul dumneavoastră. zip(p) este ca și cum ai rula zip([[1,2,3],[4,5,6]]). Zip are un singur argument aici, așa că, în mod trivial, îl returnează ca un tupluplu.

zip(*p) este ca și cum ai rula zip([1,2,3], [4,5,6]). Acest lucru este similar cu rularea zip(p[0], p[1]) și se obține rezultatul așteptat.

Kasravnd

* este cunoscut sub numele de operator de despachetare. atunci când apare în spatele unui obiect iterabil, ceea ce face este să treacă elementele din interiorul iterabilului către apelantul funcției, unul câte unul. În acest caz, din moment ce zip funcția acceptă o listă de iterabile pentru a returna coloanele aliniate ale acestora, zip(*p) transmite toate elementele din interiorul p ca argumente pentru zip funcția:

Prin urmare, în acest caz, zip(*p) este egală cu:

zip([1,2,3],[4,5,6])

De asemenea, rețineți că, începând cu Python-3.5, puteți utiliza operatorii de despachetare în alte câteva cazuri decât în apelanții de funcții. Unul dintre acestea se numește „in-place unpacking”, care vă permite să utilizați unpacking în cadrul unui alt iterabil.

In [4]: a = [1, 2, 3]

In [5]: b = [8, 9, *a, 0, 0]

In [6]: b
Out[6]: [8, 9, 1, 2, 3, 0, 0]

vermillon

Pe scurt, cu x = [1,2,3], , atunci când se apelează f(x), , x primește 1 argument [1, 2, 3]. Atunci când se utilizează operatorul stea f(*x), , f primește 3 argumente, este echivalent cu apelul f(1,2,3).

Acesta este motivul pentru care, în documentația Python, veți vedea adesea some_function(*args, **kwargs). Aici, operatorul stea dublă face același lucru, dar pentru un dicționar: cu d={"some_arg":2, "some_other_arg":3}, , apelând f(**d) este același lucru cu f(some_arg=2, some_other_arg=3).

Acum, când folosiți zip, doriți efectiv să comprimați [1,2,3] cu [4,5,6], deci doriți să treceți 2 argumente către zip, prin urmare aveți nevoie de un operator stea. Fără acesta, treceți doar un singur argument.

Comentarii

  • O funcție definiție cu operatorul * sau ** ca cea pe care ați menționat-o este o utilizare diferită a lui * operator. În acest context, acesta este utilizat pentru a crea funcții variadice. Acestea sunt legate de * despre care vorbește OP, care este mai degrabă un fel de zahăr sintactic pentru apply operator. Este o idee proastă să le confundați pe amândouă. –  > Por Noufal Ibrahim.
  • Eu aș spune că sunt două fațete ale aceluiași concept (deși au comportamente diferite). Într-un caz (definirea funcției), specificați că funcția va accepta mai multe argumente grupate sub un singur nume (args), în timp ce în celălalt caz faceți ca un singur nume să expedieze mai multe argumente. Așadar, desigur că sunt diferite, dar sunt concepte sintactice strâns legate între ele și înțelegerea uneia vă face să o înțelegeți pe cealaltă. –  > Por vermillon.
  • După cum am spus, sunt legate, dar având în vedere lipsa de expertiză în domeniu a celui care a pus întrebarea, acest lucru va deruta mai degrabă decât să instruiască. –  > Por Noufal Ibrahim.
  • Destul de corect. Să sperăm că va săpa mai mult. –  > Por vermillon.
tobloef

Deși acesta nu este răspunsul la întrebarea pe care ați pus-o, ar trebui să vă ajute. Deoarece zip este folosit pentru a combina două liste, ar trebui să faceți ceva de genul acesta list(zip(p[0], p[1])) pentru a obține ceea ce vă așteptați.

generalpiston

Operatorul „*” despachetează o listă și o aplică unei funcții. Operatorul zip ia n liste și creează n perechi de n-tuple din fiecare element din ambele liste:

zip([iterabil, …])

Această funcție returnează o listă de tuple, în care al i-lea tuplule conține al i-lea element din fiecare dintre secvențele de argumente sau iterabile. Lista returnată este trunchiată în lungime până la lungimea celei mai scurte secvențe de argumente. În cazul în care există mai multe argumente care au toate aceeași lungime, zip() este similară cu map() cu un argument inițial None. În cazul unui singur argument de secvență, se returnează o listă de 1-tuple. Dacă nu conține niciun argument, trimite o listă goală.

Practic, prin utilizarea * cu [[1,2,3],[4,5,6]], , se transmite [1,2,3] și [4,5,6] ca argumente pentru zip.