Apakah ada fungsi 'foreach' di Python 3?


148

Ketika saya menemui situasi saya bisa melakukannya dalam javascript, saya selalu berpikir jika ada foreachfungsi itu akan memudahkan. Yang saya maksud dengan foreach adalah fungsi yang dijelaskan di bawah ini:

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

mereka hanya melakukannya pada setiap elemen dan tidak menghasilkan atau mengembalikan sesuatu, saya pikir itu harus menjadi fungsi bawaan dan harus lebih cepat daripada menulisnya dengan Python murni, tetapi saya tidak menemukannya di daftar, atau itu hanya menyebut nama lain? atau saya hanya melewatkan beberapa poin di sini?

Mungkin saya salah, karena memanggil fungsi dengan Python membutuhkan biaya tinggi, jelas bukan praktik yang baik misalnya. Daripada loop keluar, fungsi harus melakukan loop di samping tubuhnya terlihat seperti ini di bawah ini yang telah disebutkan dalam banyak saran kode python:

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

tetapi saya pikir semua masih diterima berdasarkan dua fakta:

  1. Dalam kasus normal, orang tidak peduli dengan kinerja
  2. Terkadang API tidak menerima objek yang dapat diulang dan Anda tidak dapat menulis ulang sumbernya.

3
Apa salahnya menggunakan forloop?

1
Inilah tepatnya untuk apa for.
user2357112 mendukung Monica

2
tidak ada yang salah dengan for loop, hanya untuk kenyamanan
user2003548

6
@ user2357112, sebaiknya memiliki singkatan untuk memanggil suatu fungsi sekali per item dari daftar. list.each(func)lebih bersih dari for item in list: func(item), IMO. Masalahnya adalah bahwa Python telah melakukan pekerjaan yang baik untuk mengganti favorit fungsional seperti map()dan filter()dengan pemahaman daftar yang hanya memperluas bawaannya fordan if(yang homogen dan dapat dibaca) dan yang spesifik .each()mungkin bertentangan dengan itu.
sevko

sum(0 for _ in map(f, seq))adalah solusi yang bisa dibaca.
Johannes Schaub - litb

Jawaban:


180

Setiap kemunculan "foreach" yang pernah saya lihat (PHP, C #, ...) pada dasarnya sama dengan pernyataan "untuk" ular sanca.

Ini kurang lebih setara:

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

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

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

Jadi, ya, ada "foreach" di python. Ini disebut "untuk".

Apa yang Anda gambarkan adalah fungsi "peta larik". Ini bisa dilakukan dengan pemahaman daftar di python:

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

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

5
Ini bukan map (), karena map () mengumpulkan dan mengembalikan daftar, sedangkan foreach () tidak. Perbedaannya bisa sangat mahal jika Anda mengulang daftar item yang panjang. Setuju bahwa untuk () melakukan trik.
Canuck

2
Saya telah melihat ini disebut sebagai for-in loop.
Vox

6
Mereka menanyakan tentang fungsi, tetapi Anda menjawab dengan untuk pernyataan.
Johannes Schaub - litb

@ JohannesSchaub-litb masalahnya adalah bahwa dia benar ... 'karena' dalam python secara harfiah berarti 'foreach' yang dikenal dalam bahasa lain ... dalam tcl untuk misalnya loop 'untuk' akan menjadi seperti untuk {hal-hal yang dijalankan di awal loop} {kondisi di sini} {hal-hal yang berjalan pada setiap iterasi} {perintah di sini ...} misalnya: untuk {set x 1} {$ x <= 10} {incr x} {put $ x} Anda juga dapat menambahkan ekstra periksa di dalam kurung iterasi menggunakan ';'. Bagi saya akan lebih masuk akal jika dia datang ke sini menanyakan apakah python memiliki loop 'untuk' yang benar
Francisco

3
@Francisco Saya juga benar mengatakan bahwa bumi tidak datar. Tapi saya tidak akan menambahkannya sebagai jawaban.
Johannes Schaub - litb

50

Python tidak memiliki foreachpernyataan itu sendiri . Ini memiliki forloop yang dibangun ke dalam bahasa.

for element in iterable:
    operate(element)

Jika Anda benar-benar menginginkannya, Anda dapat menentukan foreachfungsi Anda sendiri :

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

Sebagai catatan tambahan for element in iterablesintaksnya berasal dari bahasa pemrograman ABC , salah satu pengaruh Python.


14
Jika Anda melakukan ini untuk efek samping, bukan untuk hasil pemetaan, maka menggunakan mapdengan cara ini tidak benar-benar akan berhasil di Python 3 mapyang malas. Artinya, sekarang mengembalikan iterator, bukan daftar yang sudah dihitung. Efek samping tidak akan terjadi sampai Anda mengulang melalui daftar yang dihasilkan.
Laurence Gonsalves

Itu benar dan tentu saja poin yang valid, tetapi pertanyaannya menunjukkan OP mungkin tidak peduli dengan seluk-beluk semacam itu.
Phillip Cloud

@LaurenceGonsves Terima kasih. Saya telah mengedit untuk membuat contoh pertama benar dengan Python 3.
Phillip Cloud

Ini jelek, hampir sepanjang forloop, dan jika iterable panjang (mungkin tak terbatas) atau nilai kembalian fungsi besar, ia akan putus dengan a MemoryError.
user2357112 mendukung Monica

1
Diedit untuk menghapus diskusi peta.
Phillip Cloud

31

Contoh lain:

Lingkaran Kedepan Python:

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

Python Untuk 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

10

map dapat digunakan untuk situasi yang disebutkan dalam pertanyaan.

Misalnya

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

Untuk fungsi yang mengambil banyak argumen, lebih banyak argumen dapat diberikan ke peta:

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

Ini mengembalikan daftar di python 2.x dan iterator di python 3

Jika fungsi Anda mengambil banyak argumen dan argumen tersebut sudah dalam bentuk tupel (atau yang dapat diulang sejak python 2.6) yang dapat Anda gunakan itertools.starmap. (yang memiliki sintaks yang sangat mirip dengan apa yang Anda cari). Ini mengembalikan sebuah iterator.

Misalnya

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

memberi kita 8 dan 9


3
mapdan foreachmemiliki arti yang berbeda. mapmengembalikan daftar hasil (yang menyiratkan membuat daftar, atau struktur yang dapat dihitung, atau struktur yang akan dikonsumsi, dan karena itu tidak langsung dipanggil), foreachmemanggil fungsi pada setiap item, mengabaikan hasilnya.
njzk2

1
Foreachharus segera mengembalikan hasilnya. Mengatakan bahwa membuat iterator daripada foreach lebih disukai adalah omong kosong total.
Alien Kecil

1
Menggunakan map()saat hasil diabaikan adalah anti-pola. Anda harus menggunakan for loop sebagai gantinya.
odie5533

2
Menggunakan mapdan mengabaikan hasil akan menghasilkan hasil yang tidak diinginkan dalam Python 3 karena mapsekarang malas dievaluasi hanya ketika daftar yang dihasilkan dipakai. Jika hasil dari maptidak pernah dikonsumsi, panggilan tidak akan pernah diterapkan.
Dmitry B.

5

Ini melakukan foreach di python 3

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

for fetch in test:
    print(fetch)

8
Ini tidak menjawab pertanyaan itu.
Boiethios


2

Jika saya mengerti Anda benar, maksud Anda adalah jika Anda memiliki fungsi 'func', Anda ingin memeriksa setiap item dalam daftar jika func (item) mengembalikan nilai true; jika Anda benar untuk semua, maka lakukan sesuatu.

Anda bisa menggunakan 'semua'.

Sebagai contoh: Saya ingin mendapatkan semua bilangan prima dalam kisaran 0-10 dalam daftar:

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

Berikut adalah contoh konstruksi "foreach" dengan akses simultan ke indeks elemen dengan Python:

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

1

Lihat artikel ini . Objek iterator nditer dari paket numpy , yang diperkenalkan di NumPy 1.6, menyediakan banyak cara fleksibel untuk mengunjungi semua elemen dari satu atau lebih larik secara sistematis.

Contoh:

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

Jika Anda hanya mencari sintaks yang lebih ringkas, Anda dapat meletakkan loop for pada satu baris:

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

Pisahkan saja pernyataan tambahan dengan titik koma.

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

Ini mungkin tidak sesuai dengan panduan gaya lokal Anda, tetapi masuk akal untuk melakukannya seperti ini saat Anda bermain-main di konsol.


0

Saya rasa ini menjawab pertanyaan Anda, karena ini seperti lingkaran "untuk setiap".
Script di bawah ini valid dalam python (versi 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)")
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.