0
votes

Quand et pourquoi l'interprète se défait-t-il en supposant des sublistes de même longueur?

Je suis impressionné par et que vous profiterez du fait qu'un simple Python pour code> instruction peut facilement démêler une liste de listes, sans avoir besoin de numpy.unravel code> ou un équivalent Fonction aplatir. Cependant, le compromis est maintenant que je ne peux pas accéder aux éléments d'une liste comme ceci: xxx pré>

et à la place, cela fonctionne jusqu'à la longueur-1 [5] CODE>: P>

for a,b,c in [[1,2,3],[4,5,6],[7,8,9],[0,0,0], [5]]:
     print(a,b,c)

1 2 3
4 5 6
7 8 9
0 0 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 1)


6 commentaires

pour a, b, c dans [[5], [6], [7]]: a absolument rien à faire avec NUMPY. C'est une liste de python. Ni ne pour a, b, c dans [[1,2,3], [4,5,6], [7,8,9], [0,0,0], [5]]:


Tout d'abord, vous ne traitez pas de comportement numpy . C'est une itération de Python de base. Deuxièmement, vous semblez confondre deux éléments - le pour itération et le a, b, c déballage. Le déballage est inflexible en ce qui concerne les éléments numériques qu'il s'attend, dans ce cas 3 (une valeur pour chaque variable). De plus, il ne vous permet pas de supposer quoi que ce soit - il soulève une exécution ValueError si vous vous trompez. (Cette inadéquation n'est pas une erreur de syntaxe).


Python n'assume rien. Cela vous permet de déballer tout iérent . C'est à vous de vous assurer que vos itérables ont le nombre attendu d'articles.


"Comment se fait-il alors, Python nous permet de supposer qu'une liste de listes aurait toujours le même nombre d'éléments?" - même raison pour laquelle vous suppose supposer qu'une liste a au moins 3 éléments lorsque vous faites l [2] ou pourquoi il vous permet de supposer que chaque élément d'une liste est un numéro lorsque vous écrivez pour x dans l: s + = x . Pourquoi ne te laisserais-t-il pas?


Il existe des moyens de «démêler» des séquences avec des sous-séquences inégales. Voir la question zip_longest sans FillValue .


Je suis désolé si ma question n'était pas claire. Je ne supposais pas que cette fonctionnalité n'avait aucune référence engourdie. J'essayais juste de dessiner des parallèles à la fonctionnalité de NP.Unravel de Numpy, comme une suppression de ce que fait l'interprète. Merci @martineau pour clarifier la question.


3 Réponses :


3
votes

L'interpréteur toujours em> suppose que la longueur correspond à une affectation de déballage et se bloque simplement avec ValueError code> s'il ne correspond pas. Une boucle pour la boucle est en fait très similaire à une sorte d'une sorte de "déclaration d'affectation répétée", avec le LHS étant la variable (s) libre (s) de la boucle et le RHS étant un conteneur itérable donnant la valeur successive à utiliser dans chaque étape. de l'itération.

Une attribution par itération, faite au début de l'organisme de boucle - dans votre cas, c'est une affectation de déballage, qui lie plusieurs noms. P>

Donc, afin d'être correctement équivalente au deuxième exemple. , votre premier exemple qui était: p> xxx pré>

aurait dû être écrit à la place: p> xxx pré>

Il n'y a pas de "anticipation", et il ne peut y avoir pas parce que (dans le cas général), vous pouvez être itérant sur n'importe quoi, par exemple Streaming de données dans une prise. P>

Afin de saisir complètement la manière dont le flux de boucle fonctionne, l'analogie avec des relevés d'affectation est très utile. Tout ce que vous pouvez utiliser sur le côté gauche d'une instruction d'affectation, vous pouvez utiliser comme cible dans une boucle. Par exemple, cela équivaut à définir d [1] = 2 code> etc. dans une dict - et doit faire le même résultat que dict (rhs) code>: p>

>>> d = {}
>>> for k, d[k] in [[1, 2], [3, 4]]: 
...     pass 
...
>>> d
{1: 2, 3: 4}


2 commentaires

Pas assez; Il aurait besoin d'être: pour [A], [b], [c], [[[[[5], [6], [7]]]]: (notez des supports supplémentaires sur la chose en cours d'itération ). Sinon, il tenterait de déballer [5] à [a], [b], [c] .


Votre approche post-modification fonctionne également :-). Comme indique pour [A] dans [[5], [6], [7]]: . Je vais arrêter avant d'entrer dans Plusieurs façons de déballer les listes d'éléments à un seul élément ... :-)



3
votes

Python ne sait pas, vous venez de dit cela s'attendre à trois éléments en déballant à trois noms. Le ValueError dit "Vous nous avez dit trois, mais nous avons trouvé un sous-iTable qui n'avait pas trois éléments, et nous ne savons pas quoi faire".

python n'est pas vraiment faire n'importe quoi spécial pour la mettre en œuvre; Outre des cas spéciaux pour types intégrés tels que tuple (et probablement ), la mise en œuvre est juste pour itérer le nombre de fois prévu et vider tous les Valeurs trouvées sur la pile d'interpréter, puis rangez-les aux noms fournis. Il essaie également d'itérer une fois de plus (attente stopiteration ) afin de ne pas ignorer silencieusement des valeurs supplémentaires.

Pour des cas limités, vous pouvez être flexible en ayant l'un des déballums. Noms précédés d'un * , de sorte que vous capturez tous les éléments "N'a pas adaptés" dans ce nom (comme liste ). Cela vous permet de définir un nombre minimum d'éléments tout en permettant davantage, par exemple. Si vous n'avez vraiment besoin que du premier élément de votre deuxième exemple, vous pouvez faire: xxx

_ n'est qu'un nom qui, par convention, signifie "Je ne me soucie pas de cette valeur, mais j'avais besoin d'un nom d'espace réservé".

Un autre exemple serait lorsque vous voulez le premier et le dernier élément, mais sinon vous ne vous souciez pas du milieu: xxx

mais sinon, si vous devez gérer des itérables de longueur variable, ne pas déballer, il suffit de magasiner sur un seul nom et d'itéréter le nom manuellement de votre sens. logique de programme.


0 commentaires

3
votes

Python n'assume pas les mêmes listes de longueurs car ceci n'est pas seulement pour les listes.

Lorsque vous itérez pour A, B, C dans [[1,2,3], [4,5,6]. [7,8,9], [0,0,0], [5]] Code> Ce qui se passe est que Python renvoie un Itérateur qui ira détestera (renvoyer) chaque liste de liste. P>

de sorte que pour cela équivaut à: p>

a,b,c = [1,2,3]
a,b,c = [4,5,6]
a,b,c = [7,8,9]
a,b,c = [0,0,0]
a,b,c = [5]


1 commentaires

Je suggérerais d'illustrer avec suivant (l_iter) , pas l_iter.next () ; Ce dernier est faux dans Python 3 (où le nom est __ suivant __ ), tandis que le niveau supérieur suivant () fonction intégré fonctionne sur 2.7 et 3.x (et est L'approche généralement approuvée, de la même manière len (SEQ) est préférée sur seq .__ len __ () , même si techniquement, travaillez).