Python 3 中是否有 'foreach' 函数?

236

每当我遇到可以用JavaScript实现的情况时,我总是在想是否有一个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无法接受可迭代对象,而你无法重写其源代码。

4
仅使用“for”循环有什么问题吗? - user395760
1
这正是for用来做的。 - user2357112
3
for循环没有问题,只是为了方便。 - user2003548
15
在处理列表中的每个元素时,希望有一个简洁的方式来调用函数。在我看来,list.each(func)for item in list: func(item) 更加清晰。问题是,Python 已经成功地用列表推导式取代了一些函数式编程喜爱的方法,如 map()filter(),而这些列表推导式使用内置的 forif 语句(它们是同构且易读的),加入一个特定的 .each() 可能会违背这种趋势。 - sevko
sum(0 for _ in map(f, seq)) 是一种易读的解决方法。 - Johannes Schaub - litb
这个问题不清楚,因为 OP 使用 foreach 来表示某些非标准的意思。实际上,对于那些拥有它的语言,foreach 通常只是与 Python 的 for 相同,而 OP 似乎正在寻找像 map 或列表推导式一样的东西,以便将某个输入序列的每个元素应用一个函数。根据一些答案,似乎 OP 还认为有某种基于序列的方法。本质上,这些答案显示出 OP 被多种不同的方式解释了,并且这里的所有材料都可以通过其他问题更好地解决。 - Karl Knechtel
15个回答

270

我看到的所有“foreach”出现(PHP,C#等)基本上与Python的“for”语句相同。

以下两者大致等效:

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

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

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

是的,Python 中有 "foreach" 功能,它被称为 "for"。

你描述的是 "array map" 函数。在 Python 中可以使用列表推导式完成此操作:

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

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

8
不是使用map(),因为map()会累积并返回一个列表,而foreach()则不会。如果你要迭代长列表中的项目,则这种差异可能会很昂贵。同意使用for()来完成这个任务。 - Canuck
5
我已经看到这被称为“for-in”循环。 - Vox
10
他们询问函数,但你却回答了关于for循环的语句。 - Johannes Schaub - litb
1
@JohannesSchaub-litb 的观点是正确的...在Python中,“for”就是其他语言中所称的“foreach”...例如,在tcl中,“for”循环将类似于for {stuff ran on beginning of loop} {condition here} {stuff that runs on each iteration} {commands here...},例如:for {set x 1} {$x <= 10} {incr x} {puts $x}您还可以在迭代括号内使用“;”添加额外的检查。对我来说,如果他来问Python是否有真正的“for”循环,这会更有意义。 - Francisco
3
@Francisco,我也正确地说地球不是平的。但我不会将其添加为答案。 - Johannes Schaub - litb
显示剩余2条评论

74

Python本质上没有foreach语句,但是它具有语言内置的for循环。

for element in iterable:
    operate(element)

如果你真的想要,你可以定义自己的foreach函数:

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

顺带提一下,for element in iterable 的语法来自ABC编程语言,是Python的一种影响。


16
如果您使用map而非为了获得映射结果而是为了副作用,那么在Python 3中以这种方式使用map实际上是行不通的,因为map现在是惰性的,它返回一个迭代器,而不是已计算好的列表。副作用只有在您遍历生成的列表时才会发生。 - Laurence Gonsalves
这是正确的,当然是一个有效的观点,但问题表明OP可能不关心这样的细微差别。 - Phillip Cloud
@LaurenceGonsalves 谢谢。我已经编辑过了,使第一个例子在Python 3中正确。 - Phillip Cloud
这很丑,几乎和 for 循环一样长,如果可迭代对象很长(可能是无限的)或函数返回值很大,则会因为 MemoryError 而中断。 - user2357112
1
已编辑以删除地图讨论。 - Phillip Cloud
显示剩余2条评论

36

其他例子:

Python ForEach循环:

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

Python 的 for 循环:

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

这不是 foreach 结构,而是模拟它的循环。 - WestCoastProjects
是的,它要模拟。 - uingtea

15

map可以用于问题中提到的情况。

例如:

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

对于需要多个参数的函数,可以在 map 中提供更多的参数:

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
mapforeach 的含义不同。map 返回结果列表(这意味着创建一个列表、可枚举的结构或将被使用但不会立即调用的结构),foreach 对每个项目调用函数,忽略结果。 - njzk2
1
Foreach 必须立即返回结果。说创建迭代器而不是使用 foreach 更好是完全胡说八道。 - Little Alien
2
当忽略结果时,使用map()是一种反模式。您应该改用for循环。 - odie5533
2
在Python 3中,使用map并忽略结果会产生不良后果,因为map现在是惰性求值的,只有在消耗结果列表时才会被执行。如果map的结果从未被消耗,则调用永远不会被应用。 - Dmitry B.

14

正确答案是 "Python集合没有foreach方法"。在原生的Python中,我们需要使用外部的for _element_ in _collection_语法,这不是OP想要的。

总体而言,Python在函数式编程方面相对较弱。有一些库可以缓解这种情况。我曾经帮助创作过其中一个叫做infixpy的库。

pip install infixpy https://pypi.org/project/infixpy/

from infixpy import Seq
(Seq([1,2,3]).foreach(lambda x: print(x)))
1
2
3

另请参阅:Python 3中列表操作的从左到右应用


2
这就是我一直在寻找的答案。大多数其他答案都没有明确说明Python缺乏内置的for each循环,只提供了解决方法。干杯! - CausingUnderflowsEverywhere
1
这个回答很好。大多数其他回答都处于防御模式。 - undefined

8

这里是Python中同时访问元素索引的"foreach"结构示例:

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

1
太棒了!比for idx in range(len(myList)):\print(idx,myList[idx])要干净得多,其中myList=[3, 4, 5] - Armfoot

7

是的,尽管它使用与for循环相同的语法。

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

1
很遗憾,这不是 forEach - nehem
如果您希望的话,可以将其包装在一个函数中。 - Caveman
@nehem 请查看问题。 - Caveman

5

这是在Python 3中使用foreach的方法

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

for fetch in test:
    print(fetch)

11
这并没有回答这个问题。 - Boiethios

3
看看 这篇文章。NumPy 1.6中引入的numpy包中的迭代器对象nditer提供了许多灵活的方式以系统化的方式访问一个或多个数组的所有元素。
例如:
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]]

有趣但仍不是foreach - WestCoastProjects

2

如果我理解正确的话,您想要检查列表中每个元素是否满足函数“func”的条件。如果所有元素都满足条件,则执行某些操作。

您可以使用 'all' 函数。

例如:我想在范围为 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))]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接