¿Hay una función 'foreach' en Python 3?


139

Cuando me encuentro con la situación, puedo hacerlo en javascript, siempre pienso que si hay una foreachfunción sería conveniente. Por foreach me refiero a la función que se describe a continuación:

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

simplemente lo hacen en cada elemento y no producen o devuelven algo, creo que debería ser una función incorporada y debería ser más rápido que escribirlo con Python puro, pero no lo encontré en la lista, o ¿acabo de llamar a otro nombre? ¿O acabo de perder algunos puntos aquí?

Tal vez me equivoqué, porque llamar a una función en Python cuesta mucho, definitivamente no es una buena práctica para el ejemplo. En lugar de un bucle de salida, la función debería hacer que el bucle en el lado de su cuerpo se vea así a continuación, que ya se menciona en muchas sugerencias de código de Python:

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

pero pensé que foreach todavía es bienvenido en base a los dos hechos:

  1. En casos normales, a las personas simplemente no les importa el rendimiento
  2. En algún momento, la API no aceptó el objeto iterable y no puede reescribir su fuente.

3
¿Qué tiene de malo usar un forbucle?

1
Esto es exactamente para lo que forsirve.
user2357112 es compatible con Monica el

2
no hay nada malo con el bucle, solo por conveniencia
usuario2003548

66
@ user2357112, es conveniente tener una abreviatura para llamar a una función una vez por elemento de una lista. list.each(func)es más limpio que for item in list: func(item), en mi opinión. El problema es que Python ha hecho un buen trabajo al reemplazar los favoritos funcionales como map()y filter()con las comprensiones de listas que simplemente extienden su incorporado fory if(que son homogéneos y legibles) y un específico .each()podría ir en contra de eso.
sevko

sum(0 for _ in map(f, seq))es una solución legible.
Johannes Schaub - litb

Respuestas:


171

Cada aparición de "foreach" que he visto (PHP, C #, ...) hace básicamente lo mismo que la declaración "for" de pitones.

Estos son más o menos equivalentes:

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

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

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

Entonces, sí, hay un "foreach" en python. Se llama "para".

Lo que estás describiendo es una función de "mapa de matriz". Esto podría hacerse con listas de comprensión en python:

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

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

55
No es map (), porque map () acumula y devuelve una lista, mientras foreach () no. La diferencia podría ser bastante costosa si está iterando sobre una larga lista de elementos. Acordó que for () hace el truco.
Canuck

2
He visto esto referido como un bucle for-in .
Vox

55
Le preguntaron sobre la función, pero usted respondió con una declaración.
Johannes Schaub - litb

@ JohannesSchaub-litb es que tiene razón ... 'for' en python es literalmente 'foreach' conocido en otros idiomas ... en tcl por ejemplo, un bucle 'for' sería algo así como {las cosas se ejecutaron al principio de loop} {condición aquí} {cosas que se ejecutan en cada iteración} {comandos aquí ...} por ejemplo: para {set x 1} {$ x <= 10} {incr x} {pone $ x} también puede agregar más comprueba dentro de las llaves de iteración usando ';'. Para mí tendría más sentido si él viniera aquí preguntando si Python tenía un verdadero bucle 'for'
Francisco

3
@Francisco También tengo razón al decir que la tierra no es plana. Pero no lo agregaré como respuesta.
Johannes Schaub - litb

49

Python no tiene una foreachdeclaración per se . Tiene forbucles integrados en el lenguaje.

for element in iterable:
    operate(element)

Si realmente quisiera, podría definir su propia foreachfunción:

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

Como nota al margen, la for element in iterablesintaxis proviene del lenguaje de programación ABC , una de las influencias de Python.


14
Si está haciendo esto por efectos secundarios, en lugar de por el resultado del mapeo, usarlo mapde esta manera realmente no funcionará en Python 3, donde mapes perezoso. Es decir, ahora devuelve un iterador, no una lista ya calculada. Los efectos secundarios no tendrán lugar hasta que repita la lista resultante.
Laurence Gonsalves

Eso es cierto y ciertamente un punto válido, pero la pregunta sugiere que el OP probablemente no esté preocupado por tales sutilezas.
Phillip Cloud

@LaurenceGonsalves Gracias. He editado para que el primer ejemplo sea correcto en Python 3.
Phillip Cloud

Esto es feo, es casi tan largo como el forciclo, y si el iterable es largo (quizás infinito) o los valores de retorno de la función son grandes, se rompe con a MemoryError.
user2357112 es compatible con Monica el

¿Qué es feo? El primer ejemplo? Claro, pero responde la pregunta. También mencioné el uso de un forbucle simple , así como listas de comprensiones.
Phillip Cloud

31

Otros ejemplos:

Python Foreach Loop:

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

Python para bucle:

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 puede usarse para la situación mencionada en la pregunta.

P.ej

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

Para funciones que toman múltiples argumentos, se pueden dar más argumentos para mapear:

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

Devuelve una lista en python 2.xy un iterador en python 3

En caso de que su función tome múltiples argumentos y los argumentos ya estén en forma de tuplas (o cualquier iterable desde python 2.6) puede usar itertools.starmap. (que tiene una sintaxis muy similar a la que estaba buscando). Devuelve un iterador.

P.ej

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

nos da 8 y 9


3
mapy foreachtienen un significado diferente. mapdevuelve una lista de resultados (lo que implica crear una lista, o una estructura enumerable, o una estructura que se consumirá, y por lo tanto no se llama de inmediato), foreachllama a la función en cada elemento, ignorando el resultado.
njzk2

1
Foreachdebe devolver el resultado inmediatamente. Decir que se prefiere crear iteradores en lugar de foreach es una mierda total.
Little Alien

Usar map()cuando se ignora el resultado es un antipatrón. Deberías usar un bucle for en su lugar.
odie5533

1
Usar mape ignorar los resultados producirá resultados no deseados en Python 3, ya mapque ahora se evalúa perezosamente solo cuando se consume la lista resultante. Si el resultado del mapnunca se consume, las llamadas nunca se aplican.
Dmitry B.

5

Esto hace el foreach en python 3

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

for fetch in test:
    print(fetch)

77
Esto no responde la pregunta.
Boiethios


2

Si lo entendí bien, quiere decir que si tiene una función 'func', desea verificar para cada elemento de la lista si func (item) devuelve verdadero; si te vuelves verdadero para todos, entonces haz algo.

Puedes usar 'todos'.

Por ejemplo: quiero obtener todos los números primos en el rango 0-10 en una lista:

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

Aquí está el ejemplo de la construcción "foreach" con acceso simultáneo a los índices de elementos en Python:

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

1

Mira este artículo . El objeto iterador nditer del paquete numpy , introducido en NumPy 1.6, proporciona muchas formas flexibles de visitar todos los elementos de una o más matrices de manera sistemática.

Ejemplo:

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 solo está buscando una sintaxis más concisa, puede colocar el bucle for en una línea:

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

Simplemente separe las declaraciones adicionales con un punto y coma.

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

Es posible que esto no se ajuste a su guía de estilo local, pero podría tener sentido hacerlo así cuando está jugando en la consola.


0

Creo que esto responde a su pregunta, porque es como un ciclo "para cada".
El siguiente script es válido en python (versión 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)")
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.