Có chức năng 'foreach' trong Python 3 không?


138

Khi tôi gặp tình huống tôi có thể làm điều đó trong javascript, tôi luôn nghĩ nếu có một foreachchức năng thì đó sẽ là sự tiện lợi. Theo foreach tôi có nghĩa là chức năng được mô tả dưới đây:

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

họ chỉ làm điều đó trên mọi phần tử và không mang lại hoặc trả lại một cái gì đó, tôi nghĩ rằng nó nên là một hàm dựng sẵn và sẽ nhanh hơn viết nó bằng Python thuần túy, nhưng tôi không tìm thấy nó trong danh sách, hoặc Nó chỉ gọi một tên khác? hoặc tôi chỉ bỏ lỡ một số điểm ở đây?

Có lẽ tôi đã nhầm, vì việc gọi một hàm trong Python có chi phí cao, chắc chắn không phải là một thực hành tốt cho ví dụ. Thay vì một vòng lặp ra, hàm nên thực hiện vòng lặp bên trong thân của nó trông như thế này bên dưới đã được đề cập trong nhiều đề xuất mã của python:

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

nhưng tôi nghĩ foreach vẫn được chào đón dựa trên hai sự thật:

  1. Trong trường hợp bình thường, mọi người chỉ không quan tâm đến hiệu suất
  2. Đôi khi API không chấp nhận đối tượng lặp lại và bạn không thể viết lại nguồn của nó.

3
Có gì sai khi chỉ sử dụng một forvòng lặp?

1
Đây là chính xác những gì forlà cho.
user2357112 hỗ trợ Monica

2
không có gì sai với vòng lặp, chỉ để thuận tiện
user2003548

6
@ user2357112, mong muốn có một tốc ký để gọi hàm một lần cho mỗi mục trong danh sách. list.each(func)sạch hơn for item in list: func(item)IMO. Vấn đề là Python đã hoàn thành tốt công việc thay thế các mục yêu thích chức năng như map()filter()với sự hiểu biết danh sách chỉ đơn giản là mở rộng tích hợp forif(đồng nhất và dễ đọc) và một điều cụ .each()thể có thể đi ngược lại.
Sevko

sum(0 for _ in map(f, seq))là một cách giải quyết có thể đọc được.
Julian Schaub - litb

Câu trả lời:


170

Mọi sự xuất hiện của "foreach" mà tôi đã thấy (PHP, C #, ...) về cơ bản giống như câu lệnh pythons "for".

Đây là ít nhiều tương đương:

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

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

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

Vì vậy, vâng, có một "foreach" trong python. Nó được gọi là "cho".

Những gì bạn đang mô tả là một chức năng "mảng bản đồ". Điều này có thể được thực hiện với sự hiểu biết danh sách trong python:

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

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

5
Đó không phải là map (), vì map () tích lũy và trả về một danh sách, trong khi foreach () thì không. Sự khác biệt có thể khá tốn kém nếu bạn lặp đi lặp lại trong một danh sách dài các mặt hàng. Đồng ý rằng cho () thực hiện các mẹo.
Canuck

2
Tôi đã thấy điều này được gọi là một vòng lặp for-in .
Vox

5
Họ hỏi về chức năng, nhưng bạn đã trả lời với tuyên bố.
Julian Schaub - litb

@ JohannesSchaub-litb điều là anh ấy đúng ... 'vì' trong python có nghĩa đen là 'foreach' được biết bằng các ngôn ngữ khác ... trong tcl ví dụ: vòng lặp 'for' sẽ giống như {công cụ chạy vào đầu loop} {condition here} {thứ chạy trên mỗi lần lặp} {lệnh ở đây ...} ví dụ: for {set x 1} {$ x <= 10} {tăng x} {đặt $ x} bạn cũng có thể thêm kiểm tra bên trong các dấu ngoặc lặp bằng cách sử dụng ';'. Đối với tôi sẽ có ý nghĩa hơn nếu anh ta đến đây hỏi xem con trăn có vòng lặp 'for' thực sự hay không
Francisco

3
@Francisco Tôi cũng đúng khi nói rằng trái đất không phẳng. Nhưng tôi sẽ không thêm nó như một câu trả lời.
Julian Schaub - litb

49

Python không có một foreachtuyên bố mỗi se . Nó có forcác vòng lặp được xây dựng trong ngôn ngữ.

for element in iterable:
    operate(element)

Nếu bạn thực sự muốn, bạn có thể xác định foreachchức năng của riêng mình :

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

Như một lưu ý phụ, for element in iterablecú pháp xuất phát từ ngôn ngữ lập trình ABC , một trong những ảnh hưởng của Python.


14
Nếu bạn đang làm điều này cho các hiệu ứng phụ, thay vì kết quả của ánh xạ, thì sử dụng maptheo cách này sẽ không thực sự hoạt động trong Python 3, nơi maplười biếng. Đó là, bây giờ nó trả về một iterator, không phải là một danh sách đã được tính toán. Các tác dụng phụ sẽ không diễn ra cho đến khi bạn lặp qua danh sách kết quả.
Laurence Gonsalves

Đó là sự thật và chắc chắn là một điểm hợp lệ, nhưng câu hỏi cho thấy OP có lẽ không quan tâm đến sự tinh tế như vậy.
Đám mây Phillip

@LaurenceGonsalves Cảm ơn. Tôi đã chỉnh sửa để làm cho ví dụ đầu tiên chính xác trong Python 3.
Phillip Cloud

Điều này thật xấu xí, nó gần như là forvòng lặp và nếu vòng lặp dài (có thể là vô hạn) hoặc các giá trị trả về của hàm lớn, nó sẽ bị phá vỡ bằng a MemoryError.
user2357112 hỗ trợ Monica

Có gì xấu? Ví dụ đầu tiên? Chắc chắn, nhưng nó trả lời câu hỏi. Tôi cũng đề cập đến việc chỉ sử dụng một forvòng lặp đơn giản làm việc, cũng như hiểu danh sách.
Đám mây Phillip

31

Những ví dụ khác:

Python Foreach Loop:

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

Python cho vòng lặp:

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

8

map có thể được sử dụng cho các tình huống được đề cập trong câu hỏi.

Ví dụ

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

Đối với các hàm có nhiều đối số, có thể đưa ra nhiều đối số hơn trên bản đồ:

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

Nó trả về một danh sách trong python 2.x và một iterator trong python 3

Trong trường hợp hàm của bạn có nhiều đối số và các đối số đã ở dạng tuples (hoặc bất kỳ lần lặp nào kể từ python 2.6), bạn có thể sử dụng itertools.starmap. (có một cú pháp rất giống với những gì bạn đang tìm kiếm). Nó trả về một iterator.

Ví dụ

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

cho chúng tôi 8 và 9


3
mapforeachcó ý nghĩa khác nhau. maptrả về một danh sách kết quả (ngụ ý tạo ra một danh sách, hoặc một cấu trúc có thể đếm được, hoặc một cấu trúc sẽ được tiêu thụ, và do đó không được gọi ngay lập tức), foreachgọi hàm trên mỗi mục, bỏ qua kết quả.
njzk2

1
Foreachphải trả lại kết quả ngay lập tức. Nói rằng việc tạo iterator thay vì foreach được ưu tiên là tổng số tào lao.
Người ngoài hành tinh nhỏ

Sử dụng map()khi kết quả bị bỏ qua là một mô hình chống. Bạn nên sử dụng một vòng lặp for thay thế.
odie5533

1
Việc sử dụng mapvà bỏ qua các kết quả sẽ tạo ra kết quả không mong muốn trong Python 3 vì maphiện tại chỉ được đánh giá một cách lười biếng khi danh sách kết quả được sử dụng. Nếu kết quả của mapkhông bao giờ được tiêu thụ, các cuộc gọi không bao giờ được áp dụng.
Dmitry B.

5

Điều này không có trong foreach trong python 3

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

for fetch in test:
    print(fetch)

7
Điều này không trả lời câu hỏi.
Boiethios

5

Có, mặc dù nó sử dụng cú pháp tương tự như một vòng lặp for.

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

Thật không may, đây không phải làforEach
3:24

@nehem Gói nó trong một chức năng nếu bạn muốn.
Caveman

@nehem Xem câu hỏi
Caveman

2

Nếu tôi hiểu bạn đúng, bạn có nghĩa là nếu bạn có chức năng 'func', bạn muốn kiểm tra từng mục trong danh sách nếu func (mục) trả về đúng; nếu bạn đúng với tất cả, thì hãy làm gì đó

Bạn có thể sử dụng 'tất cả'.

Ví dụ: Tôi muốn nhận tất cả các số nguyên tố trong phạm vi 0-10 trong danh sách:

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

Dưới đây là ví dụ về cấu trúc "foreach" với quyền truy cập đồng thời vào các chỉ mục phần tử trong Python:

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

1

Nhìn vào bài viết này . Đối tượng lặp lặp nditer từ gói numpy , được giới thiệu trong NumPy 1.6, cung cấp nhiều cách linh hoạt để truy cập tất cả các phần tử của một hoặc nhiều mảng theo kiểu có hệ thống.

Thí dụ:

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

Nếu bạn chỉ tìm kiếm một cú pháp ngắn gọn hơn, bạn có thể đặt vòng lặp for trên một dòng:

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

Chỉ cần tách các câu lệnh bổ sung bằng dấu chấm phẩy.

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

Điều này có thể không phù hợp với hướng dẫn phong cách địa phương của bạn, nhưng sẽ có ý nghĩa khi làm điều đó như thế này khi bạn đang chơi xung quanh trong bảng điều khiển.


0

Tôi nghĩ rằng điều này trả lời câu hỏi của bạn, bởi vì nó giống như một vòng lặp "cho mỗi".
Kịch bản dưới đây hợp lệ trong python (phiên bả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)")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.