มีฟังก์ชัน 'foreach' ใน Python 3 หรือไม่?


148

เมื่อฉันพบกับสถานการณ์ฉันสามารถทำได้ในจาวาสคริปต์ฉันมักจะคิดว่าถ้ามีforeachฟังก์ชั่นมันจะสะดวก โดย foreach ฉันหมายถึงฟังก์ชันที่อธิบายไว้ด้านล่าง:

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

พวกเขาทำมันในทุกองค์ประกอบและไม่ได้ให้ผลหรือส่งคืนบางสิ่งฉันคิดว่ามันควรจะเป็นฟังก์ชันในตัวและควรจะเร็วกว่าการเขียนด้วย Python บริสุทธิ์ แต่ฉันไม่พบมันในรายการหรือ แค่เรียกชื่ออื่น?

บางทีฉันอาจจะคิดผิดทำให้การเรียกใช้ฟังก์ชันใน Python มีราคาสูงไม่ใช่แนวทางปฏิบัติที่ดีสำหรับตัวอย่าง แทนที่จะวนรอบนอกฟังก์ชั่นควรทำวนซ้ำที่ด้านข้างตัวของมันมีลักษณะดังนี้ด้านล่างซึ่งได้กล่าวไว้แล้วในคำแนะนำโค้ดของ python หลายรายการ:

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

แต่ฉันคิดว่า foreach ยังคงเป็นที่น่ายินดีสำหรับข้อเท็จจริงสองประการ:

  1. ในกรณีปกติผู้คนไม่สนใจเกี่ยวกับประสิทธิภาพ
  2. บางครั้ง API ไม่ยอมรับออบเจ็กต์ที่ทำซ้ำได้และคุณไม่สามารถเขียนซอร์สซ้ำได้

3
มีอะไรผิดปกติกับการใช้forลูป?

1
นี่คือสิ่งที่แน่นอนforสำหรับ
user2357112 รองรับ Monica

2
ไม่มีอะไรผิดปกติสำหรับการวนซ้ำเพื่อความสะดวก
user2003548

6
@ user2357112 เป็นที่พึงปรารถนาที่จะมีชวเลขเพื่อเรียกใช้ฟังก์ชันหนึ่งครั้งต่อรายการของรายการ list.each(func)สะอาดกว่าfor item in list: func(item)IMO ปัญหาคือ Python ทำงานได้ดีในการแทนที่รายการโปรดที่ใช้งานได้เช่นmap()และfilter()ด้วยความเข้าใจในรายการซึ่งเพียงแค่ขยายในตัวforและif(ซึ่งเป็นเนื้อเดียวกันและอ่านได้) และสิ่งที่เฉพาะเจาะจง.each()อาจขัดต่อสิ่งนั้น
sevko

sum(0 for _ in map(f, seq))เป็นวิธีแก้ปัญหาที่อ่านได้
Johannes Schaub - litb

คำตอบ:


180

ทุกครั้งที่เกิดขึ้นของ "foreach" ที่ฉันเคยเห็น (PHP, C #, ... ) จะเหมือนกับคำสั่ง pythons "for"

สิ่งเหล่านี้เทียบเท่ากันมากหรือน้อย:

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

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

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

ใช่มี "foreach" ใน python เรียกว่า "สำหรับ"

สิ่งที่คุณกำลังอธิบายคือฟังก์ชัน "แผนที่อาร์เรย์" สิ่งนี้สามารถทำได้ด้วยการทำความเข้าใจรายการใน python:

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

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

5
ไม่ใช่แผนที่ () เนื่องจาก map () สะสมและส่งคืนรายการในขณะที่ foreach () ไม่ได้ ความแตกต่างอาจมีราคาค่อนข้างแพงหากคุณทำซ้ำในรายการยาว ๆ ตกลงว่าสำหรับ () ทำเคล็ดลับ
Canuck

2
ฉันเคยเห็นสิ่งนี้เรียกว่าfor-in loop
Vox

6
พวกเขาถามเกี่ยวกับฟังก์ชัน แต่คุณตอบด้วยคำสั่ง
Johannes Schaub - litb

@ JohannesSchaub-litb คือเขาพูดถูก ... 'สำหรับ' ใน python นั้นแท้จริง 'foreach' เป็นที่รู้จักในภาษาอื่น ... ใน tcl สำหรับเช่นลูป 'for' จะเป็นเช่นสำหรับ {สิ่งที่ทำงานในจุดเริ่มต้นของ loop} {เงื่อนไขที่นี่} {สิ่งที่ทำงานในการวนซ้ำแต่ละครั้ง} {คำสั่งที่นี่ ... } เช่นสำหรับ {set x 1} {$ x <= 10} {incr x} {ทำให้ $ x} คุณสามารถเพิ่มพิเศษ ตรวจสอบภายในวงเล็บปีกกาวนซ้ำโดยใช้ ";" สำหรับฉันจะสมเหตุสมผลกว่านี้ถ้าเขามาที่นี่ถามว่า python มีลูป 'for' จริงหรือไม่
Francisco

3
@ ฟรานซิสโกฉันพูดถูกเช่นกันว่าโลกไม่ได้แบน แต่ฉันจะไม่เพิ่มเป็นคำตอบ
Johannes Schaub - litb

50

งูใหญ่ไม่ได้มีforeachคำสั่งต่อ se มันมีการforวนซ้ำในภาษา

for element in iterable:
    operate(element)

หากคุณต้องการจริงๆคุณสามารถกำหนดforeachฟังก์ชันของคุณเอง:

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

ตามที่ทราบด้านข้างfor element in iterableไวยากรณ์มาจากภาษาโปรแกรมABCซึ่งเป็นหนึ่งในอิทธิพลของ Python


14
หากคุณกำลังทำสิ่งนี้เพื่อผลข้างเคียงแทนที่จะเป็นผลจากการทำแผนที่การใช้mapวิธีนี้จะไม่ได้ผลใน Python 3 ซึ่งmapเป็นเรื่องน่าเกียจ นั่นคือตอนนี้จะส่งคืนตัววนซ้ำไม่ใช่รายการที่คำนวณแล้ว ผลข้างเคียงจะไม่เกิดขึ้นจนกว่าคุณจะทำซ้ำในรายการผลลัพธ์
Laurence Gonsalves

นั่นเป็นความจริงและเป็นประเด็นที่ถูกต้อง แต่คำถามชี้ให้เห็นว่า OP อาจไม่เกี่ยวข้องกับรายละเอียดปลีกย่อยดังกล่าว
Phillip Cloud

@LaurenceGonsalves ขอบคุณ ฉันได้แก้ไขเพื่อทำให้ตัวอย่างแรกถูกต้องใน Python 3
Phillip Cloud

สิ่งนี้น่าเกลียดมันยาวเกือบเท่าforลูปและถ้าการวนซ้ำยาว (อาจไม่สิ้นสุด) หรือค่าการส่งคืนฟังก์ชันมีขนาดใหญ่มันจะแตกด้วย a MemoryError.
user2357112 รองรับ Monica

1
แก้ไขเพื่อลบการอภิปรายแผนที่
Phillip Cloud

31

ตัวอย่างอื่น ๆ :

Python Foreach Loop:

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

Python สำหรับ 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 สามารถใช้ได้กับสถานการณ์ที่กล่าวถึงในคำถาม

เช่น

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

สำหรับฟังก์ชันที่รับอาร์กิวเมนต์หลายรายการสามารถกำหนดอาร์กิวเมนต์เพิ่มเติมให้กับแผนที่ได้:

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

ส่งคืนรายการใน python 2.x และตัววนซ้ำใน python 3

ในกรณีที่ฟังก์ชันของคุณรับอาร์กิวเมนต์หลายตัวและอาร์กิวเมนต์อยู่ในรูปแบบทูเปิลแล้ว (หรือสามารถทำซ้ำได้ตั้งแต่ python 2.6) คุณสามารถitertools.starmapใช้ได้ (ซึ่งมีรูปแบบคล้ายกันมากกับสิ่งที่คุณกำลังมองหา) มันส่งคืนตัวทำซ้ำ

เช่น

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

ทำให้เรามี 8 และ 9


3
mapและforeachมีความหมายที่แตกต่างกัน mapส่งคืนรายการผลลัพธ์ (ซึ่งหมายถึงการสร้างรายการหรือโครงสร้างที่นับได้หรือโครงสร้างที่จะถูกใช้และดังนั้นจึงไม่ถูกเรียกทันที) foreachเรียกใช้ฟังก์ชันในแต่ละรายการโดยไม่สนใจผลลัพธ์
njzk2

1
Foreachจะต้องส่งคืนผลลัพธ์ทันที การบอกว่าการสร้าง iterator แทน foreach นั้นเป็นที่ต้องการทั้งหมด
Little Alien

1
การใช้map()เมื่อผลลัพธ์ถูกละเว้นเป็นการต่อต้านรูปแบบ คุณควรใช้ for loop แทน
odie5533

2
การใช้mapและเพิกเฉยต่อผลลัพธ์จะให้ผลลัพธ์ที่ไม่ต้องการใน Python 3 เนื่องจากmapขณะนี้ได้รับการประเมินอย่างเฉื่อยชาก็ต่อเมื่อมีการใช้รายการผลลัพธ์เท่านั้น หากไม่ใช้ผลลัพธ์ของmapการโทรจะไม่มีการใช้การโทร
Dmitry B.



2

ถ้าฉันเข้าใจคุณถูกต้องคุณหมายความว่าหากคุณมีฟังก์ชัน 'func' คุณต้องการตรวจสอบแต่ละรายการในรายการหาก func (รายการ) ส่งคืนจริง ถ้าคุณเป็นจริงสำหรับทุกคนแล้วทำอะไรบางอย่าง

คุณสามารถใช้ "ทั้งหมด"

ตัวอย่างเช่นฉันต้องการรับจำนวนเฉพาะทั้งหมดในช่วง 0-10 ในรายการ:

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

นี่คือตัวอย่างของโครงสร้าง"foreach"พร้อมการเข้าถึงดัชนีองค์ประกอบใน Python พร้อมกัน:

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

1

ดูบทความนี้ ตัววนซ้ำอ็อบเจ็กต์nditerจากแพ็กเกจnumpyซึ่งเปิดตัวใน NumPy 1.6 มีวิธีที่ยืดหยุ่นมากมายในการเยี่ยมชมองค์ประกอบทั้งหมดของอาร์เรย์หนึ่งหรือหลายอาร์เรย์อย่างเป็นระบบ

ตัวอย่าง:

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

หากคุณกำลังมองหาไวยากรณ์ที่กระชับมากขึ้นคุณสามารถใส่for loop ในบรรทัดเดียว:

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

เพียงคั่นข้อความเพิ่มเติมด้วยเครื่องหมายอัฒภาค

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

สิ่งนี้อาจไม่เป็นไปตามคำแนะนำสไตล์ท้องถิ่นของคุณ แต่ก็สมเหตุสมผลที่จะทำเช่นนี้เมื่อคุณเล่นในคอนโซล


0

ฉันคิดว่าสิ่งนี้ตอบคำถามของคุณได้เพราะมันเหมือนกับการวนซ้ำ
สคริปต์ด้านล่างใช้ได้ใน python (เวอร์ชัน 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)")
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.