Esiste una funzione "foreach" in Python 3?


139

Quando incontro la situazione posso farlo in javascript, penso sempre che se c'è una foreachfunzione sarebbe comodo. Per foreach intendo la funzione che è descritta di seguito:

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

lo fanno solo su ogni elemento e non hanno prodotto o restituito qualcosa, penso che dovrebbe essere una funzione integrata e dovrebbe essere più veloce della scrittura con Python puro, ma non l'ho trovato nell'elenco, o ha appena chiamato un altro nome? o mi mancano solo alcuni punti qui?

Forse ho sbagliato, perché chiamare una funzione in Python ha un costo elevato, sicuramente non è una buona pratica per l'esempio. Piuttosto che un loop out, la funzione dovrebbe eseguire il loop a lato, il suo corpo è simile al seguente, che è già stato menzionato in molti suggerimenti di codice di Python:

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

ma ho pensato che foreach sia ancora il benvenuto sulla base dei due fatti:

  1. In casi normali, alle persone semplicemente non interessa la performance
  2. A volte l'API non ha accettato l'oggetto iterabile e non è possibile riscriverne l'origine.

3
Cosa c'è di sbagliato nell'usare un forloop?

1
Questo è esattamente ciò che forserve.
user2357112 supporta Monica il

2
niente di sbagliato con for loop, solo per comodità
user2003548

6
@ user2357112, è preferibile avere una scorciatoia per chiamare una funzione una volta per ogni elemento di un elenco. list.each(func)è più pulito di for item in list: func(item), IMO. Il problema è che Python ha fatto un buon lavoro nel sostituire i preferiti funzionali come map()e filter()con la comprensione di elenchi che semplicemente estendono il suo built-in fore if(che sono omogenei e leggibili) e uno specifico .each()potrebbe andare contro questo.
Sevko,

sum(0 for _ in map(f, seq))è una soluzione leggibile.
Johannes Schaub - litb

Risposte:


171

Ogni ricorrenza di "foreach" che ho visto (PHP, C #, ...) fa sostanzialmente la stessa frase dei pitoni "for".

Questi sono più o meno equivalenti:

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

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

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

Quindi, sì, c'è un "foreach" in Python. Si chiama "per".

Quello che stai descrivendo è una funzione "array map". Questo potrebbe essere fatto con la comprensione delle liste in Python:

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

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

5
Non è map (), perché map () si accumula e restituisce un elenco, mentre foreach () no. La differenza potrebbe essere piuttosto costosa se stai ripetendo un lungo elenco di elementi. Concordato che for () fa il trucco.
Canuck,

2
Ho visto questo indicato come un ciclo for-in .
Vox,

5
Hanno chiesto la funzione, ma hai risposto con una dichiarazione.
Johannes Schaub - litb

@ JohannesSchaub-litb cosa è che ha ragione ... 'for' in python è letteralmente 'foreach' conosciuto in altre lingue ... in tcl per es. Un ciclo 'for' sarebbe qualcosa di simile a {stuff eseguito all'inizio di loop} {condizione qui} {roba che gira su ogni iterazione} {comandi qui ...} ad esempio: per {set x 1} {$ x <= 10} {incr x} {mette $ x} puoi anche aggiungere un extra controlla all'interno delle parentesi graffe di iterazione usando ';'. Per me avrebbe più senso se venisse qui chiedendo se il pitone avesse un vero ciclo "for"
Francisco,

3
@Francisco Ho anche ragione nel dire che la terra non è piatta. Ma non lo aggiungerò come risposta.
Johannes Schaub - litb

49

Python non ha una foreachdichiarazione in . Ha forloop integrati nella lingua.

for element in iterable:
    operate(element)

Se lo volessi davvero, potresti definire la tua foreachfunzione:

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

Come nota a for element in iterablemargine, la sintassi deriva dal linguaggio di programmazione ABC , una delle influenze di Python.


14
Se lo stai facendo per effetti collaterali, piuttosto che per il risultato della mappatura, l'utilizzo mapin questo modo non funzionerà davvero in Python 3 dove mapè pigro. Cioè, ora restituisce un iteratore, non un elenco già calcolato. Gli effetti collaterali non avranno luogo fino a quando non si scorre l'elenco risultante.
Laurence Gonsalves il

Questo è vero e sicuramente un punto valido, ma la domanda suggerisce che probabilmente il PO non si occupa di tali sottigliezze.
Phillip Cloud,

@LaurenceGonsalves Grazie. Ho modificato per correggere il primo esempio in Python 3.
Phillip Cloud,

Questo è brutto, è lungo quasi quanto il forciclo e se l'iterabile è lungo (forse infinito) o i valori di ritorno della funzione sono grandi, si rompe con a MemoryError.
user2357112 supporta Monica il

Cosa c'è di brutto? Il primo esempio? Certo, ma risponde alla domanda. Ho anche menzionato solo l'uso di un semplice forciclo di lavoro, nonché la comprensione dell'elenco.
Phillip Cloud,

31

Altri esempi:

Python Foreach Loop:

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

Python For Loop:

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 può essere utilizzato per la situazione menzionata nella domanda.

Per esempio

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

Per le funzioni che accettano più argomenti, è possibile assegnare più argomenti alla mappa:

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

Restituisce un elenco in Python 2.xe un iteratore in Python 3

Nel caso in cui la tua funzione accetti più argomenti e gli argomenti siano già in forma di tuple (o qualsiasi iterabile da Python 2.6), puoi usare itertools.starmap. (che ha una sintassi molto simile a quello che stavi cercando). Restituisce un iteratore.

Per esempio

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

ci dà 8 e 9


3
mape foreachhanno un significato diverso. maprestituisce un elenco di risultati (che implica la creazione di un elenco, o una struttura enumerabile, o una struttura che verrà consumata, e quindi non chiamata immediatamente), foreachchiama la funzione su ciascun elemento, ignorando il risultato.
njzk2,

1
Foreachdeve restituire il risultato immediatamente. Dire che si preferisce creare iteratore invece di foreach è una schifezza totale.
Little Alien,

L'uso map()quando il risultato viene ignorato è un anti-pattern. Dovresti usare invece un ciclo for.
odie5533,

1
L'uso mape l'ignoramento dei risultati produrrà risultati indesiderati in Python 3 poiché mapora è pigramente valutato solo quando viene consumato l'elenco risultante. Se il risultato di mapnon viene mai utilizzato, le chiamate non vengono mai applicate.
Dmitry B.

5

Questo fa la foreach in Python 3

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

for fetch in test:
    print(fetch)

7
Questo non risponde alla domanda.
Boiethios,


2

Se ti ho capito bene, intendi che se hai una funzione 'func', vuoi controllare ogni elemento nella lista se func (item) ritorna vero; se diventi vero per tutti, fai qualcosa.

Puoi usare "tutto".

Ad esempio: voglio ottenere tutti i numeri primi nell'intervallo 0-10 in un elenco:

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

Ecco l'esempio della costruzione "foreach" con accesso simultaneo agli indici degli elementi in Python:

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

1

Guardate questo articolo . L'oggetto iteratore nditer dal pacchetto numpy , introdotto in NumPy 1.6, offre molti modi flessibili per visitare tutti gli elementi di uno o più array in modo sistematico.

Esempio:

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

Se stai solo cercando una sintassi più concisa, puoi mettere il ciclo for su una riga:

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

Basta separare le dichiarazioni aggiuntive con un punto e virgola.

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

Questo potrebbe non essere conforme alla tua guida di stile locale, ma potrebbe avere senso farlo in questo modo quando giochi nella console.


0

Penso che questo risponda alla tua domanda, perché è come un ciclo "per ogni".
Lo script seguente è valido in Python (versione 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)")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.