Existe-t-il une fonction 'foreach' dans Python 3?


139

Quand je rencontre la situation, je peux le faire en javascript, je pense toujours que s'il y a une foreachfonction, ce serait pratique. Par foreach, j'entends la fonction qui est décrite ci-dessous:

def foreach(fn,iterable):
    for x in iterable:
        fn(x)

ils le font juste sur chaque élément et n'ont pas donné ou retourné quelque chose, je pense que cela devrait être une fonction intégrée et devrait être plus rapide que de l'écrire avec du Python pur, mais je ne l'ai pas trouvé sur la liste, ou il a juste appelé un autre nom? ou je manque juste quelques points ici?

Peut-être que je me suis trompé, car appeler une fonction en Python coûte cher, ce n'est certainement pas une bonne pratique pour l'exemple. Plutôt qu'une boucle de sortie, la fonction doit faire la boucle à côté de son corps ressemble à ceci ci-dessous, déjà mentionné dans de nombreuses suggestions de code de python:

def fn(*args):
    for x in args:
       dosomething

mais je pensais que foreach est toujours la bienvenue sur la base des deux faits:

  1. Dans les cas normaux, les gens ne se soucient tout simplement pas de la performance
  2. Parfois, l'API n'acceptait pas d'objet itérable et vous ne pouvez pas réécrire sa source.

3
Quel est le problème avec l'utilisation d'une forboucle?

1
C'est exactement ce à quoi ça forsert.
user2357112 prend en charge Monica

2
rien de mal avec la boucle for, juste pour plus de commodité
user2003548

6
@ user2357112, il est souhaitable d'avoir un raccourci pour appeler une fonction une fois par élément d'une liste. list.each(func)est plus propre que l' for item in list: func(item)OMI. Le problème est que Python a fait du bon travail en remplaçant les favoris fonctionnels comme map()et filter()par des listes de compréhension qui étendent simplement son intégré foret if(qui sont homogènes et lisibles) et un spécifique .each()pourrait aller à l'encontre de cela.
sevko

sum(0 for _ in map(f, seq))est une solution de contournement lisible.
Johannes Schaub - litb

Réponses:


171

Chaque occurrence de "foreach" que j'ai vue (PHP, C #, ...) fait fondamentalement la même chose que l'instruction pythons "for".

Ce sont plus ou moins équivalents:

// PHP:
foreach ($array as $val) {
    print($val);
}

// C#
foreach (String val in array) {
    console.writeline(val);
}

// Python
for val in array:
    print(val)

Donc, oui, il y a un "foreach" en python. Il s'appelle «pour».

Ce que vous décrivez est une fonction de «carte de tableau». Cela pourrait être fait avec des compréhensions de liste en python:

names = ['tom', 'john', 'simon']

namesCapitalized = [capitalize(n) for n in names]

5
Ce n'est pas map (), car map () accumule et renvoie une liste, contrairement à foreach (). La différence peut être assez coûteuse si vous parcourez une longue liste d'éléments. D'accord que pour () fait l'affaire.
Canuck

2
J'ai vu cela appelé une boucle for-in .
Vox

5
Ils ont posé des questions sur la fonction, mais vous avez répondu par une déclaration.
Johannes Schaub - litb

@ JohannesSchaub-litb chose est qu'il a raison ... 'for' en python est littéralement 'foreach' connu dans d'autres langages ... en tcl par exemple une boucle 'for' serait quelque chose comme pour {trucs exécutés au début de boucle} {condition ici} {trucs qui s'exécute à chaque itération} {commandes ici ...} ex: pour {set x 1} {$ x <= 10} {incr x} {met $ x} vous pouvez aussi ajouter des vérifie à l'intérieur des accolades d'itération en utilisant ';'. Pour moi, cela aurait plus de sens s'il venait ici pour demander si python avait une vraie boucle `` pour ''
Francisco

3
@Francisco J'ai également raison de dire que la terre n'est pas plate. Mais je ne l'ajouterai pas comme réponse.
Johannes Schaub - litb

49

Python n'a pas de foreachdéclaration en soi . Il a des forboucles intégrées dans la langue.

for element in iterable:
    operate(element)

Si vous le souhaitez vraiment, vous pouvez définir votre propre foreachfonction:

def foreach(function, iterable):
    for element in iterable:
        function(element)

En for element in iterablepassant, la syntaxe provient du langage de programmation ABC , l'une des influences de Python.


14
Si vous faites cela pour les effets secondaires, plutôt que pour le résultat du mappage, alors utiliser mapde cette manière ne fonctionnera pas vraiment dans Python 3 où mapest paresseux. Autrement dit, il renvoie maintenant un itérateur, pas une liste déjà calculée. Les effets secondaires ne se produiront pas tant que vous n'aurez pas parcouru la liste résultante.
Laurence Gonsalves

C'est vrai et certainement un point valable, mais la question suggère que le PO n'est probablement pas concerné par de telles subtilités.
Phillip Cloud

@LaurenceGonsalves Merci. J'ai modifié pour que le premier exemple soit correct en Python 3.
Phillip Cloud

C'est moche, c'est presque aussi long que la forboucle, et si l'itérable est long (peut-être infini) ou si les valeurs de retour de la fonction sont grandes, cela rompt avec un MemoryError.
user2357112 prend en charge Monica

Qu'est-ce qui est moche? Le premier exemple? Bien sûr, mais cela répond à la question. J'ai également mentionné que l'utilisation d'une forboucle simple fonctionne, ainsi que des compréhensions de liste.
Phillip Cloud

31

Autres exemples:

Boucle Python Foreach:

array = ['a', 'b']
for value in array:
    print(value)
    # a
    # b

Python pour la boucle:

array = ['a', 'b']
for index in range(len(array)):
    print("index: %s | value: %s" % (index, array[index]))
    # index: 0 | value: a
    # index: 1 | value: b

9

map peut être utilisé pour la situation mentionnée dans la question.

Par exemple

map(len, ['abcd','abc', 'a']) # 4 3 1

Pour les fonctions qui prennent plusieurs arguments, plus d'arguments peuvent être donnés à mapper:

map(pow, [2, 3], [4,2]) # 16 9

Il renvoie une liste en python 2.x et un itérateur en python 3

Dans le cas où votre fonction prend plusieurs arguments et que les arguments sont déjà sous la forme de tuples (ou de tout autre itérable depuis python 2.6), vous pouvez utiliser itertools.starmap. (qui a une syntaxe très similaire à ce que vous recherchiez). Il renvoie un itérateur.

Par exemple

for num in starmap(pow, [(2,3), (3,2)]):
    print(num)

nous donne 8 et 9


3
mapet foreachont une signification différente. maprenvoie une liste de résultat (ce qui implique de créer une liste, ou une structure énumérable, ou une structure qui sera consommée, et donc pas appelée tout de suite), foreachappelle la fonction sur chaque élément, ignorant le résultat.
njzk2

1
Foreachdoit renvoyer le résultat immédiatement. Dire qu'il est préférable de créer un itérateur au lieu de foreach est une merde totale.
Little Alien

Utiliser map()lorsque le résultat est ignoré est un anti-motif. Vous devriez utiliser une boucle for à la place.
odie5533 du

1
Utiliser mapet ignorer les résultats produira des résultats indésirables dans Python 3 car il mapest maintenant évalué paresseusement uniquement lorsque la liste résultante est consommée. Si le résultat de l ' mapn'est jamais consommé, les appels ne sont jamais appliqués.
Dmitry B.

5

Cela fait le foreach en python 3

test = [0,1,2,3,4,5,6,7,8,"test"]

for fetch in test:
    print(fetch)

7
Cela ne répond pas à la question.
Boiethios

5

Oui, bien qu'il utilise la même syntaxe qu'une boucle for.

for x in ['a', 'b']: print(x)

Malheureusement ce n'est pas le casforEach
nehem le

@nehem Enveloppez-le dans une fonction si vous le souhaitez.
Caveman

@nehem Voir la question
Caveman

2

Si je vous ai bien compris, vous voulez dire que si vous avez une fonction 'func', vous voulez vérifier pour chaque élément de la liste si func (item) renvoie true; si vous devenez vrai pour tous, faites quelque chose.

Vous pouvez utiliser «tout».

Par exemple: je veux obtenir tous les nombres premiers compris entre 0 et 10 dans une liste:

from math import sqrt
primes = [x for x in range(10) if x > 2 and all(x % i !=0 for i in range(2, int(sqrt(x)) + 1))]

2

Voici l'exemple de la construction "foreach" avec accès simultané aux index des éléments en Python:

for idx, val in enumerate([3, 4, 5]):
    print (idx, val)

1

Regardez cet article . L'objet itérateur nditer du package numpy , introduit dans NumPy 1.6, fournit de nombreuses façons flexibles de visiter tous les éléments d'un ou plusieurs tableaux de manière systématique.

Exemple:

import random
import numpy as np

ptrs = np.int32([[0, 0], [400, 0], [0, 400], [400, 400]])

for ptr in np.nditer(ptrs, op_flags=['readwrite']):
    # apply random shift on 1 for each element of the matrix
    ptr += random.choice([-1, 1])

print(ptrs)

d:\>python nditer.py
[[ -1   1]
 [399  -1]
 [  1 399]
 [399 401]]

1

Si vous recherchez simplement une syntaxe plus concise, vous pouvez mettre la boucle for sur une seule ligne:

array = ['a', 'b']
for value in array: print(value)

Séparez simplement les instructions supplémentaires par un point-virgule.

array = ['a', 'b']
for value in array: print(value); print('hello')

Cela peut ne pas être conforme à votre guide de style local, mais il peut être judicieux de le faire ainsi lorsque vous jouez dans la console.


0

Je pense que cela répond à votre question, car c'est comme une boucle «pour chaque».
Le script ci-dessous est valide en python (version 3.8):

a=[1,7,77,7777,77777,777777,7777777,765,456,345,2342,4]
if (n := len(a)) > 10:
    print(f"List is too long ({n} elements, expected <= 10)")
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.