Traitement des itérables sans boucle – Real Python

By | septembre 30, 2020

Cours Python en ligne

Python carte() est une fonction intégrée qui vous permet de traiter et de transformer tous les éléments en un itérable sans utiliser un explicite pour loop, une technique communément appelée mapping. carte() est utile lorsque vous devez appliquer un fonction de transformation à chaque élément d'un itérable et les transformer en un nouvel itérable. carte() est l'un des outils qui prennent en charge un style de programmation fonctionnel en Python.

Dans ce didacticiel, vous apprendrez:

  • Comment Python carte() travaux
  • Comment transformer différents types d'itérables Python utilisant carte()
  • Comment combiner carte() avec d'autres outils fonctionnels pour effectuer des transformations plus complexes
  • Quels outils pouvez-vous utiliser pour remplacer carte() et améliorez votre code Pythonique

Grâce à ces connaissances, vous pourrez utiliser carte() efficacement dans vos programmes ou, alternativement, pour utiliser des compréhensions de listes ou des expressions génératrices pour rendre votre code plus pythonique et lisible.

Pour une meilleure compréhension de carte(), quelques connaissances préalables sur la façon de travailler avec les itérables, pour boucles, fonctions et lambda fonctions seraient utiles.

Codage avec style fonctionnel en Python

Dans programmation fonctionnelle, les calculs sont effectués en combinant des fonctions qui prennent des arguments et renvoient une ou plusieurs valeurs concrètes en conséquence. Ces fonctions ne modifient pas leurs arguments d'entrée et ne changent pas l'état du programme. Ils fournissent simplement le résultat d'un calcul donné. Ces types de fonctions sont communément appelées fonctions pures.

En théorie, les programmes construits en utilisant un style fonctionnel seront plus faciles à:

  • Développer car vous pouvez coder et utiliser chaque fonction de manière isolée
  • Déboguer et tester parce que vous pouvez tester et déboguer des fonctions individuelles sans regarder le reste du programme
  • Comprendre car vous n'avez pas besoin de gérer les changements d'état tout au long du programme

La programmation fonctionnelle utilise généralement des listes, des tableaux et d'autres itérables pour représenter les données avec un ensemble de fonctions qui opèrent sur ces données et les transforment. Lorsqu'il s'agit de traiter des données avec un style fonctionnel, il existe au moins trois techniques couramment utilisées:

  1. Cartographie consiste à appliquer une fonction de transformation à un itérable pour produire un nouvel itérable. Les éléments du nouvel itérable sont produits en appelant la fonction de transformation sur chaque élément de l'itérable d'origine.

  2. Filtration consiste à appliquer un prédicat ou une fonction à valeur booléenne à un itérable pour générer un nouvel itérable. Les éléments du nouvel itérable sont produits en filtrant tous les éléments de l'itérable d'origine qui font que la fonction de prédicat renvoie false.

  3. Réduire consiste à appliquer une fonction de réduction à un itérable pour produire une seule valeur cumulative.

Selon Guido van Rossum, Python est plus fortement influencé par les langages de programmation impératifs que par les langages fonctionnels:

Je n'ai jamais considéré Python comme étant fortement influencé par les langages fonctionnels, peu importe ce que les gens disent ou pensent. J'étais beaucoup plus familier avec les langages impératifs tels que C et Algol 68 et bien que j'aie créé des fonctions objets de première classe, je ne considérais pas Python comme un langage de programmation fonctionnel. (La source)

Cependant, en 1993, la communauté Python exigeait des fonctionnalités de programmation fonctionnelles. Ils demandaient:

Ces fonctionnalités ont été ajoutées au langage grâce à la contribution d'un membre de la communauté. Aujourd'hui, carte(), filtre(), et réduire() sont des composants fondamentaux du style de programmation fonctionnelle en Python.

Dans ce didacticiel, vous aborderez l’une de ces fonctionnalités, la fonction intégrée carte(). Vous apprendrez également à utiliser les compréhensions de listes et les expressions de générateur pour obtenir les mêmes fonctionnalités que carte() de manière pythonique et lisible.

Premiers pas avec Python carte()

Parfois, vous pouvez être confronté à des situations dans lesquelles vous devez effectuer la même opération sur tous les éléments d'une entrée itérable pour créer un nouvel itérable. L'approche la plus rapide et la plus courante de ce problème consiste à utiliser un Python pour boucle. Cependant, vous pouvez également résoudre ce problème sans boucle explicite en utilisant carte().

Dans les trois sections suivantes, vous apprendrez comment carte() fonctionne et comment vous pouvez l'utiliser pour traiter et transformer des itérables sans boucle.

Compréhension carte()

carte() boucle sur les éléments d'un iterable d'entrée (ou iterables) et retourne un itérateur qui résulte de l'application d'une fonction de transformation à chaque élément de l'itérable d'entrée d'origine.

Selon la documentation, carte() prend un objet fonction et un itérable (ou plusieurs itérables) comme arguments et retourne un itérateur qui produit des éléments transformés à la demande. La signature de la fonction est définie comme suit:

carte(une fonction, itérable[[[[ iterable1, iterable2,..., iterableN])

carte() s'applique une fonction à chaque élément de itérable dans une boucle et renvoie un nouvel itérateur qui produit des éléments transformés à la demande. une fonction peut être n'importe quelle fonction Python qui prend un nombre d'arguments égal au nombre d'itérables que vous passez carte().

Ce premier argument pour carte() est un fonction de transformation. En d’autres termes, c’est la fonction qui transforme chaque élément d’origine en un nouvel élément (transformé). Même si la documentation Python appelle cet argument une fonction, il peut s'agir de n'importe quel Python appelable. Cela inclut les fonctions intégrées, les classes, les méthodes, lambda fonctions et fonctions définies par l'utilisateur.

L'opération qui carte() exécute est communément appelé un cartographie car il mappe chaque élément d'une entrée itérable à un nouvel élément dans un itérable résultant. Pour faire ça, carte() applique une fonction de transformation à tous les éléments de l'itérable d'entrée.

Pour mieux comprendre carte(), supposons que vous deviez prendre une liste de valeurs numériques et la transformer en une liste contenant la valeur carrée de chaque nombre de la liste d'origine. Dans ce cas, vous pouvez utiliser un pour boucle et code quelque chose comme ceci:

>>>

>>> Nombres = [[[[1, 2, 3, 4, 5]
>>> au carré = []

>>> pour num dans Nombres:
...     au carré.ajouter(num ** 2)
...

>>> au carré
[1, 4, 9, 16, 25]

Lorsque vous exécutez cette boucle sur Nombres, vous obtenez une liste de valeurs carrées. le pour la boucle se répète Nombres et applique une opération d'alimentation sur chaque valeur. Enfin, il stocke les valeurs résultantes dans au carré.

Vous pouvez obtenir le même résultat sans utiliser de boucle explicite en utilisant carte(). Jetez un œil à la réimplémentation suivante de l'exemple ci-dessus:

>>>

>>> def carré(nombre):
...     revenir nombre ** 2
...

>>> Nombres = [[[[1, 2, 3, 4, 5]

>>> au carré = carte(carré, Nombres)

>>> liste(au carré)
[1, 4, 9, 16, 25]

carré() est une fonction de transformation qui mappe un nombre à sa valeur carrée. L'appel à carte() s'applique carré() à toutes les valeurs de Nombres et renvoie un itérateur qui donne des valeurs carrées. Alors tu appelles liste() sur carte() pour créer un objet liste contenant les valeurs carrées.

Puisque carte() est écrit en C et est hautement optimisé, sa boucle implicite interne peut être plus efficace qu'un Python classique pour boucle. C'est l'un des avantages de l'utilisation carte().

Un deuxième avantage de l'utilisation carte() est lié à la consommation de mémoire. Avec un pour boucle, vous devez stocker la liste entière dans la mémoire de votre système. Avec carte(), vous obtenez des éléments à la demande et un seul élément se trouve dans la mémoire de votre système à un moment donné.

Pour un autre exemple, disons que vous devez convertir tous les éléments d'une liste d'une chaîne en un nombre entier. Pour ce faire, vous pouvez utiliser carte() de même que int () comme suit:

>>>

>>> str_nums = [[[["4", "8", "6", "5", "3", "2", "8", "9", "2", "5"]

>>> int_nums = carte(int, str_nums)
>>> int_nums


>>> liste(int_nums)
[4, 8, 6, 5, 3, 2, 8, 9, 2, 5]

>>> str_nums
["4", "8", "6", "5", "3", "2", "8", "9", "2", "5"]

carte() s'applique int () à chaque valeur dans str_nums. Puisque carte() renvoie un itérateur (un objet cartographique), vous aurez besoin d'un appel liste() afin que vous puissiez épuiser l'itérateur et le transformer en objet liste. Notez que la séquence d'origine n'est pas modifiée au cours du processus.

En utilisant carte() Avec différents types de fonctions

Vous pouvez utiliser n'importe quel type de Python appelable avec carte(). La seule condition serait que l'appelable prenne un argument et renvoie une valeur concrète et utile. Par exemple, vous pouvez utiliser des classes, des instances qui implémentent une méthode spéciale appelée __appel__(), méthodes d'instance, méthodes de classe, méthodes statiques et fonctions.

Il existe des fonctions intégrées que vous pouvez utiliser avec carte(). Considérez les exemples suivants:

>>>

>>> Nombres = [[[[-2, -1, 0, 1, 2]

>>> abs_values = liste(carte(abdos, Nombres))
>>> abs_values
[2, 1, 0, 1, 2]

>>> liste(carte(flotte, Nombres))
[-2.0, -1.0, 0.0, 1.0, 2.0]

>>> mots = [[[["Bienvenue", "à", "Réel", "Python"]

>>> liste(carte(len, mots))
[7, 2, 4, 6]

Vous pouvez utiliser n'importe quelle fonction intégrée avec carte(), à condition que la fonction prenne un argument et renvoie une valeur.

Un modèle courant que vous verrez lors de l'utilisation carte() est d'utiliser un lambda fonction comme premier argument. lambda fonctions sont pratiques lorsque vous devez passer une fonction basée sur une expression à carte(). Par exemple, vous pouvez réimplémenter l'exemple des valeurs carrées à l'aide d'un lambda fonction comme suit:

>>>

>>> Nombres = [[[[1, 2, 3, 4, 5]

>>> au carré = carte(lambda num: num ** 2, Nombres)

>>> liste(au carré)
[1, 4, 9, 16, 25]

lambda les fonctions sont très utiles lorsqu'il s'agit d'utiliser carte(). Ils peuvent jouer le rôle du premier argument pour carte(). Vous pouvez utiliser lambda fonctionne avec carte() pour traiter et transformer rapidement vos itérables.

Traitement de plusieurs itérables d'entrée avec carte()

Si vous fournissez plusieurs itérables à carte(), alors la fonction de transformation doit accepter autant d'arguments que d'itérables que vous transmettez. Chaque itération de carte() passera une valeur de chaque itérable comme argument à une fonction. L'itération s'arrête à la fin de l'itérable le plus court.

Prenons l'exemple suivant qui utilise pow ():

>>>

>>> first_it = [[[[1, 2, 3]
>>> second_it = [[[[4, 5, 6, 7]

>>> liste(carte(pow, first_it, second_it))
[1, 32, 729]

pow () prend deux arguments, X et y, et retourne X à la puissance de y. Dans la première itération, X sera 1, y sera 4, et le résultat sera 1. Dans la deuxième itération, X sera 2, y sera 5, et le résultat sera 32, etc. L'itérable final est aussi long que l'itérable le plus court, qui est first_it dans ce cas.

Cette technique vous permet de fusionner deux ou plusieurs itérables de valeurs numériques à l'aide de différents types d'opérations mathématiques. Voici quelques exemples qui utilisent lambda fonctions pour effectuer différentes opérations mathématiques sur plusieurs itérables d'entrée:

>>>

>>> liste(carte(lambda X, y: X - y, [[[[2, 4, 6], [[[[1, 3, 5]))
[1, 1, 1]

>>> liste(carte(lambda X, y, z: X + y + z, [[[[2, 4], [[[[1, 3], [[[[7, 8]))
[10, 15]

Dans le premier exemple, vous utilisez une opération de soustraction pour fusionner deux itérables de trois éléments chacun. Dans le deuxième exemple, vous additionnez les valeurs de trois itérables.

Transformer les itérables de chaînes avec Python carte()

Lorsque vous travaillez avec des itérables d'objets chaîne, vous pourriez être intéressé par la transformation de tous les objets à l'aide d'une sorte de fonction de transformation. Python carte() peut être votre allié dans ces situations. Les sections suivantes vous guideront à travers quelques exemples d'utilisation carte() pour transformer les itérables des objets chaîne.

Utilisation des méthodes de str

Une approche assez courante de la manipulation de chaînes consiste à utiliser certaines des méthodes de la classe str pour transformer une chaîne donnée en une nouvelle chaîne. Si vous avez affaire à des itérables de chaînes et que vous devez appliquer la même transformation à chaque chaîne, vous pouvez utiliser carte() ainsi que diverses méthodes de chaîne:

>>>

>>> string_it = [[[["En traitement", "chaînes", "avec", "carte"]
>>> liste(carte(str.capitaliser, string_it))
['Processing', 'Strings', 'With', 'Map']

>>> liste(carte(str.plus haut, string_it))
['PROCESSING', 'STRINGS', 'WITH', 'MAP']

>>> liste(carte(str.inférieur, string_it))
['processing', 'strings', 'with', 'map']

Vous pouvez effectuer quelques transformations sur chaque élément de string_it en utilisant carte() et méthodes de chaîne. La plupart du temps, vous utilisez des méthodes qui n'acceptent pas d'arguments supplémentaires, comme str.capitalize (), str.lower (), str.swapcase (), str.title (), et str.upper ().

Vous pouvez également utiliser certaines méthodes qui acceptent des arguments supplémentaires avec des valeurs par défaut, telles que str.strip (), qui prend un argument facultatif appelé carboniser qui par défaut supprime les espaces:

>>>

>>> with_spaces = [[[["En traitement ", "chaînes", "avec   ", "carte"]

>>> liste(carte(str.bande, with_spaces))
['processing', 'strings', 'with', 'map']

Lorsque vous utilisez str.strip () comme ça, vous comptez sur la valeur par défaut de carboniser. Dans ce cas, vous utilisez carte() pour supprimer tous les espaces dans les éléments de with_spaces.

Cette technique peut être pratique lorsque, par exemple, vous traitez des fichiers texte dans lesquels les lignes peuvent comporter des espaces de fin (ou d’autres caractères) et que vous devez les supprimer. Si tel est le cas, vous devez considérer que l'utilisation str.strip () sans coutume carboniser supprimera également le caractère de nouvelle ligne.

Supprimer la ponctuation

Lorsqu'il s'agit de traiter du texte, vous devez parfois supprimer les signes de ponctuation qui restent après avoir divisé le texte en mots. Pour résoudre ce problème, vous pouvez créer une fonction personnalisée qui supprime les signes de ponctuation d'un seul mot à l'aide d'une expression régulière qui correspond aux signes de ponctuation les plus courants.

Voici une implémentation possible de cette fonction en utilisant sous(), qui est une fonction d'expression régulière qui vit dans le module dans la bibliothèque standard de Python:

>>>

>>> importer 

>>> def remove_punctuation(mot):
...     revenir .sous(r'[!?.:;,"()-]', "", mot)

>>> remove_punctuation("...Python!")
'Python'

À l'intérieur remove_punctuation (), vous utilisez un modèle d'expression régulière qui correspond aux signes de ponctuation les plus courants que vous trouverez dans tout texte rédigé en anglais. L'appel à re.sub () remplace les signes de ponctuation correspondants à l'aide d'une chaîne vide ("") et renvoie un nettoyé mot.

Une fois votre fonction de transformation en place, vous pouvez utiliser carte() pour exécuter la transformation sur chaque mot de votre texte. Voici comment cela fonctionne:

>>>

>>> texte = "" "Certaines personnes, confrontées à un problème, pensent
... "Je sais, j'utiliserai des expressions régulières."
... Maintenant, ils ont deux problèmes. Jamie Zawinski "" "

>>> mots = texte.Divisé()
>>> mots
[«Certains»«gens»lorsqu'ils«sontconfrontés»à«un«problème»«pensent»[«Certains»«gens»lorsqu'ils«sontconfrontés»à«un«problème»«pensent»['Some''people''when''confronted''with''a''problem''think'['Some''people''when''confronted''with''a''problem''think'
, '"Je', 'sais,'," Je vais "," utiliser "," normal "," expressions. "',' Maintenant ',' ils ',
    "avoir", "deux", "problèmes.", "Jamie", "Zawinski"]

>>> liste(carte(remove_punctuation, mots))
['Certains''personnes''quand''ont''confronté''à''un''problème''pensent''['Certains''personnes''quand''ont''affront'''avec''un''problème''pensent''['Some''people''when''confronted''with''a''problem''think'['Some''people''when''confronted''with''a''problem''think'
'Je', 'savoir', "je vais", 'utiliser', 'régulier', 'expressions', 'maintenant', 'ils', 'ont
',' deux ',' problèmes ',' Jamie ',' Zawinski ']

Dans ce morceau de texte, certains mots incluent des signes de ponctuation. Par exemple, vous avez 'gens,' au lieu de 'gens', 'problème,' au lieu de 'problème', etc. L'appel à carte() s'applique remove_punctuation () à chaque mot et supprime tout signe de ponctuation. Alors, dans le second liste, vous avez nettoyé les mots.

Notez que l'apostrophe (') ne fait pas partie de votre expression régulière car vous souhaitez conserver des contractions comme Mauvais comme ils sont.

Implémentation d'un algorithme de chiffrement César

Jules César, l'homme d'État romain, protégeait les messages qu'il envoyait à ses généraux en les chiffrant à l'aide d'un chiffrement. Un chiffre César décale chaque lettre d'un certain nombre de lettres. Par exemple, si vous décalez la lettre une par trois, alors tu reçois la lettre , etc.

Si le décalage dépasse la fin de l'alphabet, il vous suffit de revenir au début de l'alphabet. Dans le cas d'une rotation par trois, X deviendrait une. Voici à quoi ressemblerait l'alphabet après la rotation:

  • Alphabet original: abcdefghijklmnopqrstuvwxyz
  • Alphabet tourné par trois: defghijklmnopqrstuvwxyzabc

Le code suivant implémente rotate_chr (), une fonction qui prend un caractère et le fait pivoter de trois. rotate_chr () renverra le caractère pivoté. Voici le code:

    1 def rotate_chr(c):
    2     rot_by = 3
    3     c = c.inférieur()
    4     alphabet = "abcdefghijklmnopqrstuvwxyz"
    5     # Gardez la ponctuation et les espaces
    6     si c ne pas dans alphabet:
    7         revenir c
    8     rotated_pos = ord(c) + rot_by
    9     # Si la rotation est à l'intérieur de l'alphabet
dix     si rotated_pos <= ord(alphabet[[[[-1]):
11         revenir chr(rotated_pos)
12     # Si la rotation dépasse l'alphabet
13     revenir chr(rotated_pos - len(alphabet))

À l'intérieur rotate_chr (), vous vérifiez d'abord si le caractère est dans l'alphabet. Sinon, vous renvoyez le même caractère. Cela a pour but de conserver les signes de ponctuation et autres caractères inhabituels. À la ligne 8, vous calculez la nouvelle position de rotation du caractère dans l'alphabet. Pour ce faire, vous utilisez la fonction intégrée ord ().

ord () prend un caractère Unicode et renvoie un entier qui représente le Point de code Unicode du caractère d'entrée. Par exemple, ord ("a") Retour 97, et ord ("b") Retour 98:

>>>

>>> ord("une")
97
>>> ord("b")
98

ord () prend un caractère comme argument et renvoie le point de code Unicode du caractère d'entrée.

Si vous ajoutez cet entier au nombre cible de rot_by, puis vous obtiendrez la position de rotation de la nouvelle lettre dans l'alphabet. Dans cet exemple, rot_by est 3. Alors, la lettre "une" tourné par trois deviendra la lettre à la position 100, qui est la lettre "ré". La lettre "b" tourné par trois deviendra la lettre à la position 101, qui est la lettre "e", etc.

Si la nouvelle position de la lettre ne dépasse pas la position de la dernière lettre (alphabet[-1]), puis vous renvoyez la lettre à cette nouvelle position. Pour ce faire, vous utilisez la fonction intégrée chr ().

chr () est l'inverse de ord (). Il prend un entier représentant le point de code Unicode d'un caractère Unicode et renvoie le caractère à cette position. Par exemple, chr (97) reviendra 'une', et chr (98) reviendra «b»:

>>>

>>> chr(97)
'une'
>>> chr(98)
«b»

chr () prend un entier qui représente le point de code Unicode d'un caractère et renvoie le caractère correspondant.

Enfin, si la nouvelle position tournée est au-delà de la position de la dernière lettre (alphabet[-1]), puis vous devez revenir au début de l'alphabet. Pour ce faire, vous devez soustraire la longueur de l'alphabet de la position de rotation (rotated_pos - len (alphabet)) puis renvoyez la lettre à cette nouvelle position en utilisant chr ().

Avec rotate_chr () comme fonction de transformation, vous pouvez utiliser carte() pour crypter n'importe quel texte à l'aide de l'algorithme de chiffrement Caesar. Voici un exemple qui utilise str.join () pour concaténer la chaîne:

>>>

>>> "".joindre(carte(rotate_chr, "Mon message secret va ici."))
«pb vhfuhw phvvdjh jrhv khuh.»

Les chaînes sont également itérables en Python. Alors, l'appel à carte() s'applique rotate_chr () à chaque caractère de la chaîne d'entrée d'origine. Dans ce cas, "M" devient "p", "y" devient "b", etc. Enfin, l'appel à str.join () concatène chaque caractère pivoté dans un message chiffré final.

Transformer les itérables des nombres avec Python carte()

carte() a également un grand potentiel en matière de traitement et de transformation d'itérables de valeurs numériques. Vous pouvez effectuer une grande variété d'opérations mathématiques et arithmétiques, convertir des valeurs de chaîne en nombres à virgule flottante ou en nombres entiers, etc.

Dans les sections suivantes, vous découvrirez quelques exemples d'utilisation carte() pour traiter et transformer des itérables de nombres.

Utilisation des opérations mathématiques

Un exemple courant d'utilisation d'opérations mathématiques pour transformer un itérable de valeurs numériques consiste à utiliser l'opérateur power (**). Dans l'exemple suivant, vous codez une fonction de transformation qui prend un nombre et renvoie le nombre au carré et au cube:

>>>

>>> def pouvoirs(X):
...     revenir X ** 2, X ** 3
...

>>> Nombres = [[[[1, 2, 3, 4]

>>> liste(carte(pouvoirs, Nombres))
[(1, 1), (4, 8), (9, 27), (16, 64)]

pouvoirs() prend un certain nombre X et renvoie son carré et son cube. Étant donné que Python gère plusieurs valeurs de retour sous forme de tuples, chaque appel à pouvoirs() renvoie un tuple avec deux valeurs. Quand vous appelez carte() avec pouvoirs() comme argument, vous obtenez une liste de tuples contenant le carré et le cube de chaque nombre dans l'itérable d'entrée.

Il existe de nombreuses transformations liées aux mathématiques avec lesquelles vous pouvez effectuer carte(). Vous pouvez ajouter des constantes et les soustraire de chaque valeur. Vous pouvez également utiliser certaines fonctions du math module comme sqrt (), factorielle (), péché(), cos (), etc. Voici un exemple d'utilisation factorielle ():

>>>

>>> importer math

>>> Nombres = [[[[1, 2, 3, 4, 5, 6, 7]

>>> liste(carte(math.factorielle, Nombres))
[1, 2, 6, 24, 120, 720, 5040]

Dans ce cas, vous transformez Nombres dans une nouvelle liste contenant la factorielle de chaque nombre de la liste d'origine.

Vous pouvez effectuer un large spectre de transformations mathématiques sur un itérable de nombres en utilisant carte(). L'étendue de ce sujet dépendra de vos besoins et de votre imagination. Réfléchissez-y et codez vos propres exemples!

Conversion des températures

Un autre cas d'utilisation pour carte() est de convertir entre unités de mesure. Supposons que vous ayez une liste de températures mesurées en degrés Celsius ou Fahrenheit et que vous deviez les convertir en températures correspondantes en degrés Fahrenheit ou Celsius.

Vous pouvez coder deux fonctions de transformation pour accomplir cette tâche:

def to_fahrenheit(c):
    revenir 9 / 5 * c + 32

def to_celsius(F):
    revenir (F - 32) * 5 / 9

to_fahrenheit () prend une mesure de température en Celsius et effectue la conversion en Fahrenheit. De même, to_celsius () prend une température en Fahrenheit et la convertit en Celsius.

Ces fonctions seront vos fonctions de transformation. Vous pouvez les utiliser avec carte() pour convertir un itérable de mesures de température respectivement en Fahrenheit et en Celsius:

>>>

>>> celsius_temps = [[[[100, 40, 80]
>>> # Convertir en Fahrenheit
>>> liste(carte(to_fahrenheit, celsius_temps))
[212.0, 104.0, 176.0]

>>> fahr_temps = [[[[212, 104, 176]
>>> # Convertir en Celsius
>>> liste(carte(to_celsius, fahr_temps))
[100.0, 40.0, 80.0]

Si vous appelez carte() avec to_fahrenheit () et celsius_temps, puis vous obtenez une liste des mesures de température en Fahrenheit. Si vous appelez carte() avec to_celsius () et fahr_temps, puis vous obtenez une liste des mesures de température en degrés Celsius.

Pour étendre cet exemple et couvrir tout autre type de conversion d'unité, il vous suffit de coder une fonction de transformation appropriée.

Conversion de chaînes en nombres

Lorsque vous travaillez avec des données numériques, vous êtes probablement confronté à des situations dans lesquelles toutes vos données sont des valeurs de chaîne. Pour effectuer d'autres calculs, vous devez convertir les valeurs de chaîne en valeurs numériques. carte() peut également aider dans ces situations.

Si vous êtes sûr que vos données sont propres et ne contiennent pas de mauvaises valeurs, vous pouvez utiliser flotte() ou int () directement selon vos besoins. Voici quelques exemples:

>>>

>>> # Convertir en virgule flottante
>>> liste(carte(flotte, [[[[«12,3», «3,3», "-15,2"]))
[12.3, 3.3, -15.2]

>>> # Convertir en entier
>>> liste(carte(int, [[[["12", "3", "-15"]))
[12, 3, -15]

Dans le premier exemple, vous utilisez flotte() avec carte() pour convertir toutes les valeurs des valeurs de chaîne en valeurs à virgule flottante. Dans le second cas, vous utilisez int () pour convertir une chaîne en un entier. Notez que si l'une des valeurs n'est pas un nombre valide, vous obtiendrez un ValueError.

Si vous n'êtes pas sûr que vos données soient propres, vous pouvez utiliser une fonction de conversion plus élaborée comme celle-ci:

>>>

>>> def flotter(nombre):
...     essayer:
...         revenir flotte(nombre.remplacer(",", "."))
...     sauf ValueError:
...         revenir flotte("nan")
...

>>> liste(carte(flotter, [[[[«12,3», "3,3", "-15,2", "Un"]))
[12.3, 3.3, -15.2, nan]

À l'intérieur flotter(), vous utilisez un essayer déclaration qui attrape un ValueError si flotte() échoue lors de la conversion nombre. Si aucune erreur ne se produit, votre fonction renvoie nombre converti en un nombre à virgule flottante valide. Sinon, vous obtenez un nan (Pas un nombre), qui est une valeur spéciale flotte valeur que vous pouvez utiliser pour représenter des valeurs qui ne sont pas des nombres valides, tout comme "Un" dans l'exemple ci-dessus.

Vous pouvez personnaliser flotter() selon vos besoins. Par exemple, vous pouvez remplacer l'instruction return float ("nan") avec la déclaration retourne 0.0, etc.

Combiner carte() Avec d'autres outils fonctionnels

Jusqu'à présent, vous avez expliqué comment utiliser carte() pour accomplir différentes tâches impliquant des itérables. Cependant, si vous utilisez carte() avec d'autres outils fonctionnels comme filtre() et réduire(), vous pouvez alors effectuer des transformations plus complexes sur vos itérables. C’est ce que vous allez aborder dans les deux sections suivantes.

carte() et filtre()

Parfois, vous devez traiter une entrée itérable et renvoyer une autre itérable résultant du filtrage des valeurs indésirables dans l'itérable d'entrée. Dans ce cas, Python filtre() peut être une bonne option pour vous. filtre() est une fonction intégrée qui prend deux arguments positionnels:

  1. une fonction sera un prédicat ou une fonction à valeur booléenne, une fonction qui renvoie Vrai ou Faux selon les données d'entrée.
  2. itérable sera n'importe quel Python itérable.

filtre() donne les éléments de l'entrée itérable Pour qui une fonction Retour Vrai. Si tu réussis Aucun à une fonction, puis filtre() utilise la fonction d'identité. Cela signifie que filtre() vérifiera la valeur de vérité de chaque élément dans itérable et filtrez tous les éléments qui sont faux.

Pour illustrer comment vous pouvez utiliser carte() de même que filtre(), disons que vous devez calculer la racine carrée de toutes les valeurs d'une liste. Étant donné que votre liste peut contenir des valeurs négatives, vous obtiendrez une erreur car la racine carrée n'est pas définie pour les nombres négatifs:

>>>

>>> importer math

>>> math.sqrt(-16)
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
    math.sqrt(-16)
ValueError: erreur de domaine mathématique

Avec un nombre négatif comme argument, math.sqrt () soulève un ValueError. Pour éviter ce problème, vous pouvez utiliser filtre() pour filtrer toutes les valeurs négatives, puis trouver la racine carrée des valeurs positives restantes. Consultez l'exemple suivant:

>>>

>>> importer math

>>> def est_positif(num):
...     revenir num > = 0
...

>>> def sanitized_sqrt(Nombres):
...     nettoyé_iter = carte(math.sqrt, filtre(est_positif, Nombres))
...     revenir liste(nettoyé_iter)
...

>>> sanitized_sqrt([[[[25, 9, 81, -16, 0])
[5.0, 3.0, 9.0, 0.0]

is_positive () est une fonction de prédicat qui prend un nombre comme argument et renvoie Vrai si le nombre est supérieur ou égal à zéro. Tu peux passer is_positive () à filtre() pour supprimer tous les nombres négatifs de Nombres. Alors, l'appel à carte() traitera uniquement les nombres positifs et math.sqrt () ne vous donnera pas ValueError.

carte() et réduire()

Python réduire() est une fonction qui vit dans un module appelé functools dans la bibliothèque standard Python. réduire() est un autre outil fonctionnel de base en Python qui est utile lorsque vous devez appliquer une fonction à un itérable et le réduire à une seule valeur cumulative. Ce type d'opération est communément appelé réduction ou pliage. réduire() prend deux arguments obligatoires:

  1. une fonction peut être n'importe quel appelable Python qui accepte deux arguments et renvoie une valeur.
  2. itérable peut être n'importe quel itérable Python.

réduire() s'appliquera une fonction à tous les éléments de itérable et calculer cumulativement une valeur finale.

Voici un exemple qui combine carte() et réduire() pour calculer la taille totale de tous les fichiers qui résident dans votre répertoire personnel de manière cumulative:

>>>

>>> importer functools
>>> importer opérateur
>>> importer os
>>> importer os.path

>>> des dossiers = os.listdir(os.chemin.expanduser("~"))

>>> functools.réduire(opérateur.ajouter, carte(os.chemin.se taille, des dossiers))
4377381

Dans cet exemple, vous appelez os.path.expanduser ("~") pour obtenir le chemin de votre répertoire personnel. Alors tu appelles os.listdir () sur ce chemin pour obtenir une liste avec les chemins de tous les fichiers qui y vivent.

L'appel à carte() les usages os.path.getsize () pour obtenir la taille de chaque fichier. Enfin, vous utilisez réduire() avec operator.add () pour obtenir la somme cumulée de la taille de chaque fichier. Le résultat final est la taille totale de tous les fichiers de votre répertoire personnel en octets.

Même si vous pouvez utiliser réduire() pour résoudre le problème traité dans cette section, Python propose d'autres outils pouvant conduire à une solution plus pythonique et efficace. Par exemple, vous pouvez utiliser la fonction intégrée somme() pour calculer la taille totale des fichiers dans votre répertoire personnel:

>>>

>>> importer os
>>> importer os.path

>>> des dossiers = os.listdir(os.chemin.expanduser("~"))

>>> somme(carte(os.chemin.se taille, des dossiers))
4377381

Cet exemple est beaucoup plus lisible et efficace que l'exemple que vous avez vu auparavant. Si vous souhaitez approfondir votre utilisation réduire() et quels outils alternatifs vous pouvez utiliser pour remplacer réduire() de manière pythonique, puis consultez la réduction de Python (): du style fonctionnel au style pythonique.

Traitement des itérables basés sur des tuple avec starmap ()

Python itertools.starmap () crée un itérateur qui applique une fonction aux arguments obtenus à partir d'un itérable de tuples et donne les résultats. Cela est utile lorsque vous traitez des itérables qui sont déjà regroupés en tuples.

La principale différence entre carte() et starmap () est que ce dernier appelle sa fonction de transformation à l'aide de l'opérateur de décompression (*) pour décompresser chaque tuple d'arguments en plusieurs arguments positionnels. Ainsi, la fonction de transformation est appelée comme fonction (* args) au lieu de fonction (arg1, arg2, ... argN).

La documentation officielle pour starmap () dit que la fonction est à peu près équivalente à la fonction Python suivante:

def starmap(une fonction, itérable):
    pour args dans itérable:
        rendement une fonction(*args)

le pour boucle dans cette fonction itère sur les éléments dans itérable et produit des éléments transformés en conséquence. L'appel à fonction (* args) utilise l'opérateur de décompression pour décompresser les tuples en plusieurs arguments positionnels. Voici quelques exemples de starmap () travaux:

>>>

>>> de itertools importer starmap

>>> liste(starmap(pow, [([([([(2, 7), (4, 3)]))
[128, 64]

>>> liste(starmap(ord, [([([([(2, 7), (4, 3)]))
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
    liste(starmap(ord, [([([([(2, 7), (4, 3)]))
Erreur-type: ord () prend exactement un argument (2 donnés)

Dans le premier exemple, vous utilisez pow () pour calculer la puissance de la première valeur élevée à la deuxième valeur dans chaque tuple. Les tuples seront sous la forme (base, exposant).

Si chaque tuple de votre itérable a deux éléments, alors une fonction doit également accepter deux arguments. Si les tuples ont trois éléments, alors une fonction doit prendre trois arguments, et ainsi de suite. Sinon, vous obtiendrez un Erreur-type.

Si tu utilises carte() au lieu de starmap (), alors vous obtiendrez un résultat différent car carte() prend un élément de chaque tuple:

>>>

>>> liste(carte(pow, (2, 7), (4, 3)))
[16, 343]

Notez que carte() prend deux tuples au lieu d'une liste de tuples. carte() prend également une valeur de chaque tuple à chaque itération. Faire carte() renvoie le même résultat que starmap (), vous devez permuter les valeurs:

>>>

>>> liste(carte(pow, (2, 4), (7, 3)))
[128, 64]

Dans ce cas, vous avez deux tuples au lieu d'une liste de tuples. Vous avez également échangé 7 et 4. Maintenant, le premier tuple fournit les bases et le deuxième tuple fournit les exposants.

Codage avec style pythonique: remplacement carte()

Outils de programmation fonctionnels comme carte(), filtre(), et réduire() existent depuis longtemps. Cependant, les compréhensions de listes et les expressions génératrices sont devenues un remplacement naturel pour eux presque dans tous les cas d'utilisation.

Par exemple, la fonctionnalité fournie par carte() est presque toujours mieux exprimé en utilisant une compréhension de liste ou une expression de générateur. Dans les deux sections suivantes, vous apprendrez à remplacer un appel à carte() avec une compréhension de liste ou une expression de générateur pour rendre votre code plus lisible et pythonique.

Utilisation des compréhensions de liste

Il existe un modèle général que vous pouvez utiliser pour remplacer un appel à carte() avec une compréhension de liste. Voici comment:

# Générer une liste avec carte
liste(carte(une fonction, itérable))

# Generating a list with a list comprehension
[[[[function(X) pour X in iterable]

Note that the list comprehension almost always reads more clearly than the call to map(). Since list comprehensions are quite popular among Python developers, it’s common to find them everywhere. So, replacing a call to map() with a list comprehension will make your code look more familiar to other Python developers.

Here’s an example of how to replace map() with a list comprehension to build a list of square numbers:

>>>

>>> # Transformation function
>>> def square(number):
...     return number ** 2

>>> numbers = [[[[1, 2, 3, 4, 5, 6]

>>> # Using map()
>>> liste(map(square, numbers))
[1, 4, 9, 16, 25, 36]

>>> # Using a list comprehension
>>> [[[[square(X) pour X in numbers]
[1, 4, 9, 16, 25, 36]

If you compare both solutions, then you might say that the one that uses the list comprehension is more readable because it reads almost like plain English. Additionally, list comprehensions avoid the need to explicitly call list() on map() to build the final list.

Using Generator Expressions

map() returns a map object, which is an iterator that yields items on demand. So, the natural replacement for map() is a generator expression because generator expressions return generator objects, which are also iterators that yield items on demand.

Python iterators are known to be quite efficient in terms of memory consumption. This is the reason why map() now returns an iterator instead of a liste.

There’s a tiny syntactical difference between a list comprehension and a generator expression. The first uses a pair of square brackets ([]) to delimit the expression. The second uses a pair of parentheses (()). So, to turn a list comprehension into a generator expression, you just need to replace the square brackets with parentheses.

You can use generator expressions to write code that reads clearer than code that uses map(). Check out the following example:

>>>

>>> # Transformation function
>>> def square(number):
...     return number ** 2

>>> numbers = [[[[1, 2, 3, 4, 5, 6]

>>> # Using map()
>>> map_obj = map(square, numbers)
>>> map_obj


>>> liste(map_obj)
[1, 4, 9, 16, 25, 36]

>>> # Using a generator expression
>>> gen_exp = (square(X) pour X in numbers)
>>> gen_exp
<generator object  at 0x7f254e056890>

>>> liste(gen_exp)
[1, 4, 9, 16, 25, 36]

This code has a main difference from the code in the previous section: you change the square brackets to a pair of parentheses to turn the list comprehension into a generator expression.

Generator expressions are commonly used as arguments in function calls. In this case, you don’t need to use parentheses to create the generator expression because the parentheses that you use to call the function also provide the syntax to build the generator. With this idea, you can get the same result as the above example by calling list() like this:

>>>

>>> liste(square(X) pour X in numbers)
[1, 4, 9, 16, 25, 36]

If you use a generator expression as an argument in a function call, then you don’t need an extra pair of parentheses. The parentheses that you use to call the function provide the syntax to build the generator.

Generator expressions are as efficient as map() in terms of memory consumption because both of them return iterators that yield items on demand. However, generator expressions will almost always improve your code’s readability. They also make your code more Pythonic in the eyes of other Python developers.

Conclusion

Python’s map() allows you to perform mapping operations on iterables. A mapping operation consists of applying a transformation function to the items in an iterable to generate a transformed iterable. In general, map() will allow you to process and transform iterables without using an explicit loop.

In this tutorial, you’ve learned how map() works and how to use it to process iterables. You also learned about some Pythonic tools that you can use to replace map() in your code.

You now know how to:

  • Work with Python’s map()
  • Use map() to process et transform iterables without using an explicit loop
  • Combiner map() with functions like filter() et reduce() to perform complex transformations
  • Replace map() with tools like list comprehensions et generator expressions

With this new knowledge, you’ll be able to use map() in your code and approach your code with a functional programming style. You can also switch to a more Pythonic and modern style by replacing map() with a list comprehension or a generator expression.