Utilisation de la fonction zip () Python pour une itération parallèle – Real Python

By | octobre 2, 2019

Formation Python

Python Zip *: français() function crée un itérateur qui agrégera les éléments de deux ou plusieurs iterables. Vous pouvez utiliser l'itérateur résultant pour résoudre rapidement et de manière cohérente les problèmes de programmation courants, tels que la création de dictionnaires. Dans ce didacticiel, vous découvrirez la logique derrière Python. Zip *: français() fonction et comment vous pouvez l’utiliser pour résoudre des problèmes concrets.

À la fin de ce didacticiel, vous apprendrez:

  • Comment Zip *: français() fonctionne à la fois en Python 3 et en Python 2
  • Comment utiliser le Python Zip *: français() fonction pour itération parallèle
  • Comment créer des dictionnaires à la volée en utilisant Zip *: français()

Comprendre le python Zip *: français() Une fonction

Zip *: français() est disponible dans l'espace de noms intégré. Si tu utilises dir () inspecter __builtins__alors vous verrez Zip *: français() à la fin de la liste:

>>>

>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', ..., 'zip']

Tu peux voir ça 'Zip *: français' est la dernière entrée de la liste des objets disponibles.

Selon la documentation officielle, les informations de Python Zip *: français() fonction se comporte comme suit:

Retourne un itérateur de tuples, où le je-le tuple contient le je-th élément de chacune des séquences d'arguments ou iterables. L'itérateur s'arrête lorsque l'entrée la plus courte pouvant être itérative est épuisée. Avec un seul argument itérable, il retourne un itérateur de 1-tuples. Sans arguments, il retourne un itérateur vide. (La source)

Vous allez décompresser cette définition dans le reste du tutoriel. En parcourant les exemples de code, vous constaterez que les opérations de compression Python fonctionnent comme une fermeture à glissière physique sur un sac ou un jean. Des paires de dents imbriquées des deux côtés de la fermeture à glissière sont rapprochées pour fermer une ouverture. En fait, cette analogie visuelle est parfaite pour comprendre Zip *: français(), puisque la fonction a été nommée d'après les fermetures à glissière physiques!

En utilisant Zip *: français() en python

Python Zip *: français() fonction est définie comme zip (* iterables). La fonction prend les iterables comme arguments et retourne un itérateur. Cet itérateur génère une série de n-uplets contenant des éléments de chaque itérable. Zip *: français() peut accepter n’importe quel type d’itéré, tel que des fichiers, des listes, des n-uplets, des dictionnaires, des ensembles, etc.

Qui passe n Arguments

Si tu utilises Zip *: français() avec n arguments, alors la fonction retournera un itérateur qui générera des n-uplets de longueur n. Pour voir cela en action, regardez le bloc de code suivant:

>>>

>>> Nombres = [[[[1, 2, 3]
>>> des lettres = [[[['une', 'b', 'c']
>>> zippé = Zip *: français(Nombres, des lettres)
>>> zippé  # Détient un objet itérateur

>>> type(zippé)

>>> liste(zippé)
[(1, 'a'), (2, 'b'), (3, 'c')]

Ici, vous utilisez zip (chiffres, lettres) créer un itérateur qui produit des n-uplets de la forme (x, y). Dans ce cas, le X les valeurs proviennent de Nombres et le y les valeurs proviennent de des lettres. Remarquez comment le Python Zip *: français() fonction renvoie un itérateur. Pour récupérer l'objet liste finale, vous devez utiliser liste() consommer l'itérateur.

Si vous travaillez avec des séquences telles que des listes, des tuples ou des chaînes, il est garanti que vos itérables seront évalués de gauche à droite. Cela signifie que la liste de tuples obtenue prendra la forme [(numbers[0], des lettres[0]), (Nombres[1], des lettres[1]),..., (Nombres[n], des lettres[n])]. Cependant, pour d'autres types d'itérables (comme les ensembles), vous pourriez voir des résultats étranges:

>>>

>>> s1 = 2, 3, 1
>>> s2 = 'b', 'une', 'c'
>>> liste(Zip *: français(s1, s2))
[(1, 'a'), (2, 'c'), (3, 'b')]

Dans cet exemple, s1 et s2 sont ensemble objets, qui ne conservent pas leurs éléments dans un ordre particulier. Cela signifie que les tuples retournés par Zip *: français() aura des éléments qui sont jumelés au hasard. Si vous allez utiliser le Python Zip *: français() fonctionne avec des itérables non ordonnés comme des ensembles, alors c’est quelque chose à garder à l’esprit.

Passing No Arguments

Tu peux appeler Zip *: français() sans aucun argument aussi. Dans ce cas, vous obtiendrez simplement un itérateur vide:

>>>

>>> zippé = Zip *: français()
>>> zippé

>>> liste(zippé)
[]

Ici, vous appelez Zip *: français() sans arguments, donc votre zippé La variable contient un itérateur vide. Si vous consommez l'itérateur avec liste(), vous verrez également une liste vide.

Vous pouvez également essayer de forcer l'itérateur vide à donner directement un élément. Dans ce cas, vous obtiendrez un StopIteration exception:

>>>

>>> zippé = Zip *: français()
>>> suivant(zippé)
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
StopIteration

Quand vous appelez suivant() sur zippé, Python tente de récupérer l'élément suivant. Cependant, depuis zippé contient un itérateur vide, il n’ya rien à retirer, donc Python lève un StopIteration exception.

Passer un argument

Python Zip *: français() fonction ne peut prendre qu’un seul argument. Le résultat sera un itérateur qui produit une série de tuples à 1 élément:

>>>

>>> une = [[[[1, 2, 3]
>>> zippé = Zip *: français(une)
>>> liste(zippé)
[(1,), (2,), (3,)]

Cela peut ne pas être utile, mais cela fonctionne toujours. Peut-être que vous pouvez trouver des cas d'utilisation pour ce comportement de Zip *: français()!

Comme vous pouvez le voir, vous pouvez appeler le Python Zip *: français() fonctionne avec autant d'itérables que nécessaire. La longueur des n-uplets résultants sera toujours égale au nombre d'itérables que vous transmettez en tant qu'arguments. Voici un exemple avec trois itérables:

>>>

>>> entiers = [[[[1, 2, 3]
>>> des lettres = [[[['une', 'b', 'c']
>>> des flotteurs = [[[[4.0, 5.0, 6.0]
>>> zippé = Zip *: français(entiers, des lettres, des flotteurs)  # Trois entrées iterables
>>> liste(zippé)
[(1, 'a', 4.0), (2, 'b', 5.0), (3, 'c', 6.0)]

Ici, vous appelez le Python Zip *: français() fonctionnent avec trois itérables, de sorte que les n-uplets résultants ont trois éléments chacun.

Passer des arguments de longueur inégale

Quand vous travaillez avec le Python Zip *: français() fonction, il est important de faire attention à la longueur de vos iterables. Il est possible que les itérables que vous transmettez en arguments n’ont pas la même longueur.

Dans ces cas, le nombre d’éléments que Zip *: français() met sur sera égal à la longueur de la le plus court iterable. Les éléments restants des itérables plus longtemps seront totalement ignorés par Zip *: français(), comme vous pouvez le voir ici:

>>>

>>> liste(Zip *: français(intervalle(5), intervalle(100)))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]

Puisque 5 est la longueur de la première (et la plus courte) intervalle() objet, Zip *: français() affiche une liste de cinq tuples. Il y a encore 95 éléments incomparables de la deuxième intervalle() objet. Ce sont tous ignorés par Zip *: français() puisqu'il n'y a plus d'éléments de la première intervalle() objet pour compléter les paires.

Si les valeurs de fin ou non correspondantes sont importantes pour vous, vous pouvez utiliser itertools.zip_longest () au lieu de Zip *: français(). Avec cette fonction, les valeurs manquantes seront remplacées par ce que vous passerez au valeur de remplissage argument (par défaut à Aucun). L'itération continuera jusqu'à ce que la plus longue itérable soit épuisée:

>>>

>>> de outils informatiques importation zip_longest
>>> Nombres = [[[[1, 2, 3]
>>> des lettres = [[[['une', 'b', 'c']
>>> le plus long = intervalle(5)
>>> zippé = zip_longest(Nombres, des lettres, le plus long, valeur de remplissage='?')
>>> liste(zippé)
[(1, 'a', 0), (2, 'b', 1), (3, 'c', 2), ('?', '?', 3), ('?', '?', 4)]

Ici, vous utilisez itertools.zip_longest () pour donner cinq tuples avec des éléments de des lettres, Nombres, et le plus long. L'itération ne s'arrête que lorsque le plus long est épuisée. Les éléments manquants de Nombres et des lettres sont remplis d'un point d'interrogation ?, qui est ce que vous avez spécifié avec valeur de remplissage.

Comparant Zip *: français() en Python 3 et 2

Python Zip *: français() fonction fonctionne différemment dans les deux versions du langage. En Python 2, Zip *: français() renvoie un liste de tuples. La résultante liste est tronqué à la longueur de l'itération la plus courte. Si vous appelez Zip *: français() sans arguments, alors vous obtenez un vide liste en retour:

>>>

>>> # Python 2
>>> zippé = Zip *: français(intervalle(3), 'A B C D')
>>> zippé  # Tenir un objet de la liste
[(0, 'A'), (1, 'B'), (2, 'C')]
>>> type(zippé)

>>> zippé = Zip *: français()  # Créer une liste vide
>>> zippé
[]

Dans ce cas, votre appel au Python Zip *: français() la fonction retourne une liste de tuples tronqués à la valeur C. Quand vous appelez Zip *: français() sans argument, vous obtenez un vide liste.

En Python 3, cependant, Zip *: français() renvoie un itérateur. Cet objet donne des tuples à la demande et ne peut être parcouru qu'une fois. L'itération se termine par un StopIteration exception une fois que la plus courte entrée itérable est épuisée. Si vous ne fournissez aucun argument à Zip *: français(), alors la fonction retourne un itérateur vide:

>>>

>>> # Python 3
>>> zippé = Zip *: français(intervalle(3), 'A B C D')
>>> zippé  # Tenir un itérateur

>>> type(zippé)

>>> liste(zippé)
[(0, 'A'), (1, 'B'), (2, 'C')]
>>> zippé = Zip *: français()  # Créer un itérateur vide
>>> zippé

>>> suivant(zippé)
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
    suivant(zippé)
StopIteration

Ici, votre appel à Zip *: français() renvoie un itérateur. La première itération est tronquée à C, et le second résulte en un StopIteration exception. En Python 3, vous pouvez également émuler le comportement Python 2 de Zip *: français() en enveloppant l'itérateur retourné dans un appel à liste(). Cela passera par l'itérateur et retournera une liste de n-uplets.

Si vous utilisez régulièrement Python 2, notez que l'utilisation de Zip *: français() avec de longues entrées, iterables peut consommer beaucoup de mémoire par inadvertance. Dans ces situations, envisagez d'utiliser itertools.izip (* iterables) au lieu. Cette fonction crée un itérateur qui agrège les éléments de chacun des itérables. Il produit le même effet que Zip *: français() en Python 3:

>>>

>>> # Python 2
>>> de outils informatiques importation izip
>>> zippé = izip(intervalle(3), 'A B C D')
>>> zippé

>>> liste(zippé)
[(0, 'A'), (1, 'B'), (2, 'C')]

Dans cet exemple, vous appelez itertools.izip () créer un itérateur. Lorsque vous utilisez l'itérateur renvoyé avec liste(), vous obtenez une liste de n-uplets, comme si vous utilisiez Zip *: français() en Python 3. L'itération s'arrête lorsque la plus petite entrée itérable est épuisée.

Si vous avez vraiment besoin d'écrire du code qui se comporte de la même manière dans Python 2 et Python 3, vous pouvez utiliser une astuce comme celle-ci:

essayer:
    de outils informatiques importation izip comme Zip *: français
sauf ImportError:
    passer

Ici, si izip () est disponible dans outils informatiquesalors vous saurez que vous êtes en Python 2 et izip () sera importé en utilisant l'alias Zip *: français. Sinon, votre programme lèvera un ImportError et vous saurez que vous êtes en Python 3. (Le passer déclaration ici est juste un espace réservé.)

Avec cette astuce, vous pouvez utiliser le Python en toute sécurité Zip *: français() fonctionner tout au long de votre code. Une fois exécuté, votre programme sélectionnera et utilisera automatiquement la version correcte.

Jusqu’à présent, vous avez expliqué comment Python Zip *: français() fonctionne et a appris certaines de ses caractéristiques les plus importantes. Il est maintenant temps de retrousser vos manches et de commencer à coder des exemples concrets!

Boucle sur plusieurs itérables

Boucler sur plusieurs itérables est l’un des cas les plus courants d’utilisation de Python. Zip *: français() une fonction. Si vous devez parcourir plusieurs listes, n-uplets ou toute autre séquence, il est probable que vous utiliserez de nouveau Zip *: français(). Cette section va vous montrer comment utiliser Zip *: français() parcourir plusieurs iterables en même temps.

Parcours des listes parallèles

Python Zip *: français() fonction vous permet de parcourir en parallèle deux ou plusieurs iterables. Puisque Zip *: français() génère des n-uplets, vous pouvez les décompresser dans l’en-tête d’un pour boucle:

>>>

>>> des lettres = [[[['une', 'b', 'c']
>>> Nombres = [[[[0, 1, 2]
>>> pour l, n dans Zip *: français(des lettres, Nombres):
...     impression(F'Lettre: l')
...     impression(F'Nombre: n')
...
Lettre a
Nombre: 0
La lettre B
Numéro 1
Lettre: c
Numéro 2

Ici, vous parcourez la série de tuples renvoyés par Zip *: français() et décompressez les éléments dans l et n. Quand vous combinez Zip *: français(), pour boucles, et tuple de décompression, vous pouvez obtenir un idiome utile et Pythonic pour parcourir deux itérables ou plus à la fois.

Vous pouvez également parcourir plus de deux itérables en un seul pour boucle. Prenons l'exemple suivant, qui comporte trois itérables d'entrée:

>>>

>>> des lettres = [[[['une', 'b', 'c']
>>> Nombres = [[[[0, 1, 2]
>>> les opérateurs = [[[['*', '/', '+']
>>> pour l, n, o dans Zip *: français(des lettres, Nombres, les opérateurs):
...     impression(F'Lettre: l')
...     impression(F'Nombre: n')
...     impression(F'Opérateur: o')
...
Lettre a
Nombre: 0
Opérateur: *
La lettre B
Numéro 1
Opérateur: /
Lettre: c
Numéro 2
Opérateur: +

Dans cet exemple, vous utilisez Zip *: français() avec trois iterables pour créer et retourner un itérateur qui génère des n-uplets à 3 éléments. Cela vous permet de parcourir les trois itérables en une fois. Il n’existe aucune restriction quant au nombre d’itérables que vous pouvez utiliser avec Python. Zip *: français() une fonction.

Parcourir des dictionnaires en parallèle

Dans Python 3.6 et les versions ultérieures, les dictionnaires sont des collections ordonnées, ce qui signifie qu'ils conservent leurs éléments dans le même ordre dans lequel ils ont été introduits. Si vous profitez de cette fonctionnalité, vous pouvez utiliser le logiciel Python. Zip *: français() fonction pour parcourir plusieurs dictionnaires de manière cohérente et sûre:

>>>

>>> dict_one = 'Nom': 'John', 'nom de famille': 'Biche', 'emploi': 'Consultant Python'
>>> dict_two = 'Nom': 'Jeanne', 'nom de famille': 'Biche', 'emploi': 'Community Manager'
>>> pour (k1, v1), (k2, v2) dans Zip *: français(dict_one.articles(), dict_two.articles()):
...     impression(k1, '->', v1)
...     impression(k2, '->', v2)
...
nom -> John
nom -> Jane
nom de famille -> Doe
nom de famille -> Doe
job -> Python Consultant
job -> Community Manager

Ici, vous parcourez dict_one et dict_two en parallèle. Dans ce cas, Zip *: français() génère des n-uplets avec les éléments des deux dictionnaires. Ensuite, vous pouvez décompresser chaque tuple et accéder aux éléments des deux dictionnaires en même temps.

Notez que, dans l'exemple ci-dessus, l'ordre d'évaluation de gauche à droite est garanti. Vous pouvez également utiliser Python Zip *: français() fonction pour parcourir des ensembles en parallèle. Cependant, vous devrez considérer que, contrairement aux dictionnaires de Python 3.6, les ensembles ne pas garder leurs éléments en ordre. Si vous oubliez ce détail, le résultat final de votre programme risque de ne pas correspondre à vos attentes ou à vos attentes.

Décompression d'une séquence

Une question se pose fréquemment dans les forums de nouveaux pythonistes: «S'il y a une Zip *: français() fonction, alors pourquoi n'y at-il pas décompresser () fonction qui fait le contraire? "

La raison pour laquelle il n’existe pas décompresser () fonction en Python est parce que le contraire de Zip *: français() est bien, Zip *: français(). Vous souvenez-vous que le Python Zip *: français() la fonction fonctionne-t-elle comme une vraie fermeture éclair? Jusqu'ici, les exemples vous ont montré comment Python ferme les choses. Alors, comment décompressez-vous les objets Python?

Supposons que vous avez une liste de n-uplets et que vous souhaitez séparer les éléments de chaque tuple en séquences indépendantes. Pour ce faire, vous pouvez utiliser Zip *: français() avec l'opérateur de déballage *, ainsi:

>>>

>>> paires = [([([([(1, 'une'), (2, 'b'), (3, 'c'), (4, 'ré')]
>>> Nombres, des lettres = Zip *: français(*paires)
>>> Nombres
(1, 2, 3, 4)
>>> des lettres
('a B c d')

Ici, vous avez un liste de tuples contenant une sorte de données mélangées. Ensuite, vous utilisez l'opérateur de déballage * décompresser les données en créant deux listes différentes (Nombres et des lettres).

Tri en parallèle

Le tri est une opération courante en programmation. Supposons que vous souhaitiez combiner deux listes et les trier en même temps. Pour ce faire, vous pouvez utiliser Zip *: français() de même que .Trier() comme suit:

>>>

>>> des lettres = [[[['b', 'une', 'ré', 'c']
>>> Nombres = [[[[2, 4, 3, 1]
>>> data1 = liste(Zip *: français(des lettres, Nombres))
>>> data1
[('b', 2), ('a', 4), ('d', 3), ('c', 1)]
>>> data1.Trier()  # Trier par lettres
>>> data1
[('a', 4), ('b', 2), ('c', 1), ('d', 3)]
>>> data2 = liste(Zip *: français(Nombres, des lettres))
>>> data2
[(2, 'b'), (4, 'a'), (3, 'd'), (1, 'c')]
>>> data2.Trier()  # Trier par numéros
>>> data2
[(1, 'c'), (2, 'b'), (3, 'd'), (4, 'a')]

Dans cet exemple, vous combinez d’abord deux listes avec Zip *: français() et les trier. Remarquez comment data1 est trié par des lettres et data2 est trié par Nombres.

Vous pouvez aussi utiliser triés () et Zip *: français() ensemble pour obtenir un résultat similaire:

>>>

>>> des lettres = [[[['b', 'une', 'ré', 'c']
>>> Nombres = [[[[2, 4, 3, 1]
>>> Les données = triés(Zip *: français(des lettres, Nombres))  # Trier par lettres
>>> Les données
[('a', 4), ('b', 2), ('c', 1), ('d', 3)]

Dans ce cas, triés () traverse l'itérateur généré par Zip *: français() et trie les articles par des lettres, tout en un. Cette approche peut être un peu plus rapide car vous n’avez besoin que de deux appels de fonction: Zip *: français() et triés ().

Avec triés (), vous écrivez également un morceau de code plus général. Cela vous permettra de trier tout type de séquence, pas seulement des listes.

Calculer par paires

Vous pouvez utiliser le Python Zip *: français() fonction pour faire des calculs rapides. Supposons que vous disposiez des données suivantes dans un tableur:

Elément / Mois janvier février Mars
Ventes totales 52 000,00 51 000,00 48 000,00
Coût de production 46 800,00 45 900,00 43 200,00

Vous allez utiliser ces données pour calculer votre bénéfice mensuel. Zip *: français() peut vous fournir un moyen rapide de faire les calculs:

>>>

>>> ventes totales = [[[[52000.00, 51000.00, 48000.00]
>>> prod_cost = [[[[46800.00, 45900.00, 43200.00]
>>> pour Ventes, frais dans Zip *: français(ventes totales, prod_cost):
...     profit = Ventes - frais
...     impression(F'Bénéfice total: profit')
...
Bénéfice total: 5200.0
Bénéfice total: 5100.0
Bénéfice total: 4800,0

Ici, vous calculez le bénéfice pour chaque mois en soustrayant frais de Ventes. Python Zip *: français() Cette fonction combine les bonnes paires de données pour effectuer les calculs. Vous pouvez généraliser cette logique pour effectuer tout type de calcul complexe avec les paires renvoyées par Zip *: français().

Dictionnaires de construction

Les dictionnaires Python constituent une structure de données très utile. Parfois, vous devrez peut-être créer un dictionnaire à partir de deux séquences différentes mais étroitement liées. Un moyen pratique d'y parvenir est d'utiliser dict () et Zip *: français() ensemble. Par exemple, supposons que vous ayez récupéré les données d’une personne à partir d’un formulaire ou d’une base de données. Vous avez maintenant les listes de données suivantes:

>>>

>>> des champs = [[[['Nom', 'nom de famille', 'âge', 'emploi']
>>> valeurs = [[[['John', 'Biche', '45', 'Développeur Python']

Avec ces données, vous devez créer un dictionnaire pour un traitement ultérieur. Dans ce cas, vous pouvez utiliser dict () de même que Zip *: français() comme suit:

>>>

>>> un_dict = dict(Zip *: français(des champs, valeurs))
>>> un_dict
'name': 'John', 'last_name': 'Doe', 'age': '45', 'job': 'Développeur Python'

Ici, vous créez un dictionnaire qui combine les deux listes. zip (champs, valeurs) retourne un itérateur qui génère des tuples à 2 éléments. Si vous appelez dict () sur cet itérateur, vous construirez le dictionnaire dont vous avez besoin. Les éléments de des champs deviennent les clés du dictionnaire et les éléments de valeurs représentent les valeurs dans le dictionnaire.

Vous pouvez également mettre à jour un dictionnaire existant en combinant Zip *: français() avec dict.update (). Supposons que John change de travail et que vous deviez mettre à jour le dictionnaire. Vous pouvez faire quelque chose comme ce qui suit:

>>>

>>> nouveau travail = [[[['Consultant Python']
>>> champ = [[[['emploi']
>>> un_dict.mise à jour(Zip *: français(champ, nouveau travail))
>>> un_dict
'name': 'John', 'last_name': 'Doe', 'age': '45', 'job': 'Python Consultant'

Ici, dict.update () met à jour le dictionnaire avec le tuple clé-valeur créé à l’aide de Python Zip *: français() une fonction. Avec cette technique, vous pouvez facilement écraser la valeur de emploi.

Conclusion

Dans ce tutoriel, vous avez appris à utiliser les logiciels Python. Zip *: français() une fonction. Zip *: français() peut recevoir plusieurs iterables en entrée. Il retourne un itérateur qui peut générer des n-uplets avec des éléments appariés à partir de chaque argument. L'itérateur qui en résulte peut être très utile lorsque vous devez traiter plusieurs itérables dans une seule boucle et effectuer certaines actions sur leurs éléments en même temps.

Maintenant vous pouvez:

  • Utilisez le Zip *: français() une fonction à la fois dans Python 3 et Python 2
  • Boucle sur plusieurs iterables et effectuer différentes actions sur leurs articles en parallèle
  • Créer et mettre à jour des dictionnaires à la volée en zippant deux itérables d’entrée ensemble

Vous avez également codé quelques exemples que vous pouvez utiliser comme point de départ pour implémenter vos propres solutions à l’aide de Python. Zip *: français() une fonction. N'hésitez pas à modifier ces exemples au fur et à mesure de votre exploration Zip *: français() en profondeur!