234

When I meet the situation I can do it in javascript, I always think if there's an foreach function it would be convenience. By foreach I mean the function which is described below:

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

they just do it on every element and didn't yield or return something,i think it should be a built-in function and should be more faster than writing it with pure Python, but I didn't found it on the list,or it just called another name?or I just miss some points here?

Maybe I got wrong, cause calling an function in Python cost high, definitely not a good practice for the example. Rather than an out loop, the function should do the loop in side its body looks like this below which already mentioned in many python's code suggestions:

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

but I thought foreach is still welcome base on the two facts:

  1. In normal cases, people just don't care about the performance
  2. Sometime the API didn't accept iterable object and you can't rewrite its source.
kenorb
  • 155,785
  • 88
  • 678
  • 743
user2003548
  • 4,287
  • 5
  • 24
  • 32
  • 4
    What's wrong with just using a `for` loop? –  Aug 18 '13 at 00:30
  • 1
    This is exactly what `for` is for. – user2357112 Aug 18 '13 at 01:02
  • 3
    nothing wrong with for loop ,just for convenience – user2003548 Aug 18 '13 at 01:12
  • 15
    @user2357112, it's desirable to have a shorthand for calling a function once per item of a list. `list.each(func)` is cleaner than `for item in list: func(item)`, IMO. The problem is that Python's done a good job of replacing functional favorites like `map()` and `filter()` with list comprehensions which simply extend its built-in `for` and `if` (which are homogeneous and readable) and a specific `.each()` might go against that. – sevko Dec 09 '14 at 16:15
  • `sum(0 for _ in map(f, seq))` is a readable workaround. – Johannes Schaub - litb Jun 11 '18 at 18:44
  • This question is unclear because OP uses `foreach` to mean something nonstandard. The actual `foreach` in languages that have it is generally just the same thing as Python's `for`, whereas OP seems to be looking for something like `map` or a list comprehension, to *apply a function* to each element of some input sequence. It also seems like OP might have had in mind some kind of *method on sequences*, based on some of the answers. Essentially, the answers show that OP was interpreted in multiple different ways, and all the material here is better addressed by other questions. – Karl Knechtel Mar 07 '23 at 23:51

15 Answers15

264

Every occurence of "foreach" I've seen (PHP, C#, ...) does basically the same as pythons "for" statement.

These are more or less equivalent:

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

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

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

So, yes, there is a "foreach" in python. It's called "for".

What you're describing is an "array map" function. This could be done with list comprehensions in python:

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

namesCapitalized = [capitalize(n) for n in names]
user 451
  • 462
  • 6
  • 8
Jo Are By
  • 3,293
  • 1
  • 11
  • 11
  • 8
    It's not map(), because map() accumulates and returns a list, while foreach() doesn't. The difference could be quite expensive if you're iterating over a long list of items. Agreed that for() does the trick. – Canuck Apr 08 '15 at 17:10
  • 5
    I've seen this referred to as a __for-in__ loop. – Vox Jul 09 '15 at 21:23
  • 10
    They asked about for function, but you answered with for statement. – Johannes Schaub - litb Jun 12 '18 at 07:08
  • 1
    @JohannesSchaub-litb thing is that he is right... 'for' in python is literally 'foreach' known in other languages...in tcl for eg a 'for' loop would be something like for {stuff ran on beginning of loop} {condition here} {stuff that runs on each iteration} {commands here...} eg: for {set x 1} {$x <= 10} {incr x} {puts $x} you can also add extra checks inside the iteration braces using ';'. To me would make more sense if he came here asking if python had a true 'for' loop – Francisco Jan 18 '19 at 07:40
  • 3
    @Francisco I'm also right in saying that earth isn't flat. But I won't add it as an answer. – Johannes Schaub - litb Jan 18 '19 at 17:44
  • 1
    Is there a `foreach($array as key=>$value)` in python? – LF00 Oct 24 '19 at 00:26
  • This is not a solid answer since `foreach` is supported natively in many languages including scala, javascript, java, ruby. The difference is they are methods _on the collection itself_ not an add on external syntax. E.g. javascript `mylist.foreach( x => // do something with/to x)` – WestCoastProjects Dec 19 '20 at 10:06
73

Python doesn't have a foreach statement per se. It has for loops built into the language.

for element in iterable:
    operate(element)

If you really wanted to, you could define your own foreach function:

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

As a side note the for element in iterable syntax comes from the ABC programming language, one of Python's influences.

Phillip Cloud
  • 24,919
  • 11
  • 68
  • 88
  • 16
    If you're doing this for side-effects, rather than for the result of the mapping, then using `map` in this way isn't really going to work in Python 3 where `map` is lazy. That is, it now returns an iterator, not an already computed list. The side-effects won't take place until you iterate through the resulting list. – Laurence Gonsalves Aug 18 '13 at 00:38
  • That's true and certainly a valid point, but the question suggests the OP is probably not concerned with such subtleties. – Phillip Cloud Aug 18 '13 at 00:41
  • @LaurenceGonsalves Thanks. I've edited to make the first example correct in Python 3. – Phillip Cloud Aug 18 '13 at 00:48
  • This is ugly, it's almost as long as the `for` loop, and if the iterable is long (perhaps infinite) or the function return values are large, it breaks with a `MemoryError`. – user2357112 Aug 18 '13 at 01:05
  • What's ugly? The first example? Sure, but it answers the question. I also mentioned just using a plain `for` loop works, as well as list comprehensions. – Phillip Cloud Aug 18 '13 at 01:16
  • `map` and `foreach` are two different abstractions. `map` is supposed to return a new value while `foreach` returns no value at all. I guess the first statement in your answer leads to down votes. – yatskevich Jun 09 '16 at 13:55
  • 1
    Edited to remove the map discussion. – Phillip Cloud Jun 11 '16 at 17:18
36

Other examples:

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
uingtea
  • 6,002
  • 2
  • 26
  • 40
15

map can be used for the situation mentioned in the question.

E.g.

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

For functions that take multiple arguments, more arguments can be given to map:

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

It returns a list in python 2.x and an iterator in python 3

In case your function takes multiple arguments and the arguments are already in the form of tuples (or any iterable since python 2.6) you can use itertools.starmap. (which has a very similar syntax to what you were looking for). It returns an iterator.

E.g.

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

gives us 8 and 9

Akshit Khurana
  • 674
  • 6
  • 14
  • 3
    `map` and `foreach` have different meaning. `map` returns a list of result (which implies creating a list, or an enumerable structure, or a structure that will be consumed, and therefore not called right away), `foreach` calls the function on each item, ignoring the result. – njzk2 Jun 28 '16 at 20:46
  • 1
    `Foreach` must return the result imediately. Saying that creating iterator instead of foreach is preferred is total crap. – Little Alien Jul 12 '16 at 18:35
  • 2
    Using `map()` when the result is ignored is an anti-pattern. You should use a for loop instead. – odie5533 Jul 23 '19 at 14:22
  • 2
    Using `map` and ignoring the results will produce undesired results in Python 3 since `map` is now lazily evaluated only when the resulting list is consumed. If the result of the `map` is never consumed, the calls are never applied. – Dmitry B. Dec 14 '19 at 06:31
11

The correct answer is "python collections do not have a foreach". In native python we need to resort to the external for _element_ in _collection_ syntax which is not what the OP is after.

Python is in general quite weak for functionals programming. There are a few libraries to mitigate a bit. I helped author one of these 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

Also see: Left to right application of operations on a list in Python 3

WestCoastProjects
  • 58,982
  • 91
  • 316
  • 560
8

Here is the example of the "foreach" construction with simultaneous access to the element indexes in Python:

for idx, val in enumerate([3, 4, 5]):
    print (idx, val)
simhumileco
  • 31,877
  • 16
  • 137
  • 115
  • 1
    This is brilliant! Much cleaner than `for idx in range(len(myList)):\print(idx,myList[idx])` where `myList=[3, 4, 5]`. – Armfoot Dec 07 '20 at 21:07
7

Yes, although it uses the same syntax as a for loop.

for x in ['a', 'b']: print(x)
Caveman
  • 2,527
  • 1
  • 17
  • 18
5

This does the foreach in python 3

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

for fetch in test:
    print(fetch)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
veera sai
  • 102
  • 1
  • 1
3

Look at this article. The iterator object nditer from numpy package, introduced in NumPy 1.6, provides many flexible ways to visit all the elements of one or more arrays in a systematic fashion.

Example:

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]]
FooBar167
  • 2,721
  • 1
  • 26
  • 37
2

If I understood you right, you mean that if you have a function 'func', you want to check for each item in list if func(item) returns true; if you get true for all, then do something.

You can use 'all'.

For example: I want to get all prime numbers in range 0-10 in a list:

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))]
Pang
  • 9,564
  • 146
  • 81
  • 122
2

If you really want you can do this:

[fn(x) for x in iterable]

But the point of the list comprehension is to create a list - using it for the side effect alone is poor style. The for loop is also less typing

for x in iterable: fn(x)
AutomatedMike
  • 1,454
  • 13
  • 27
  • 1
    I scrolled past this answer, caught a glimpse of the list comprehension being used for side effects, and screeched to a halt, all ready to do the "don't use a list comprehension for side effects" spiel. Then scrolled back to the answer, read it, and realized you'd done it already :) – Pranav Hosangadi Jan 27 '23 at 04:39
2

I know this is an old thread but I had a similar question when trying to do a codewars exercise.

I came up with a solution which nests loops, I believe this solution applies to the question, it replicates a working "for each (x) doThing" statement in most scenarios:

for elements in array:
    while elements in array:
        
        array.func()
Dharman
  • 30,962
  • 25
  • 85
  • 135
ET-13
  • 21
  • 3
1

If you're just looking for a more concise syntax you can put the for loop on one line:

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

Just separate additional statements with a semicolon.

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

This may not conform to your local style guide, but it could make sense to do it like this when you're playing around in the console.

aris
  • 22,725
  • 1
  • 29
  • 33
0

In short, the functional programming way to do this is:

def do_and_return_fn(og_fn: Callable[[T], None]):
    def do_and_return(item: T) -> T:
        og_fn(item)
        return item
    return do_and_return

# where og_fn is the fn referred to by the question. 
# i.e. a function that does something on each element, but returns nothing.
iterable = map(do_and_return_fn(og_fn), iterable)

All of the answers that say "for" loops are the same as "foreach" functions are neglecting the point that other similar functions that operate on iters in python such as map, filter, and others in itertools are lazily evaluated.

Suppose, I have an iterable of dictionaries coming from my database and I want to pop an item off of each dictionary element when the iterator is iterated over. I can't use map because pop returns the item popped, not the original dictionary.

The approach I gave above would allow me to achieve this if I pass lambda x: x.pop() as my og_fn,

What would be nice is if python had a built-in lazy function with an interface like I constructed:

foreach(do_fn: Callable[[T], None], iterable: Iterable)

Implemented with the function given before, it would look like:

def foreach(do_fn: Callable[[T], None], iterable: Iterable[T]) -> Iterable[T]:
    return map(do_and_return_fn(do_fn), iterable)

# being called with my db code. 
# Lazily removes the INSERTED_ON_SEC_FIELD on every element:
doc_iter = foreach(lambda x: x.pop(INSERTED_ON_SEC_FIELD, None), doc_iter)
0

No there is no from functools import foreach support in python. However, you can just implement in the same number of lines as the import takes, anyway:

foreach = lambda f, iterable: (*map(f, iterable),)

Bonus: variadic support: foreach = lambda f, iterable, *args: (*map(f, iterable, *args),) and you can be more efficient by avoiding constructing the tuple of Nones

Tom Huntington
  • 2,260
  • 10
  • 20
  • Assigning a lambda to a variable is a code-smell. If a `foreach` function is deemed a must-have (IMO it is not, since for loops exist), you might as well define a function and while you're at it, make it a regular for loop -- code isn't written on paper so lines of code don't cost more. See a similar answer here: https://stackoverflow.com/a/2682075/843953, where the comment echoes this sentiment. I must admit though, the use of `deque` is a cool trick. – Pranav Hosangadi Jan 27 '23 at 04:36
  • @PranavHosangadi Op wanted a `from functools import foreach`. My answer does it in the same number of lines, which I believe is more readable than doing it in multiple lines with `def` and `for`. Lines of code cost the reader. I'm a big believer in aggressive inlining and named lambdas. Does having a more readable, implementation really outweigh the cost of the clutter of multiple lines? – Tom Huntington Jan 27 '23 at 06:30
  • 2
    A reader is going to spend more time deciphering that lambda than a simple function that uses a for loop. People (especially once you've had some programming experience) read _blocks_ of code, not _lines_. As for the separate "named lambda" issue: https://stackoverflow.com/questions/38381556/is-it-pythonic-naming-lambdas – Pranav Hosangadi Jan 27 '23 at 06:36
  • @PranavHosangadi the reader should be able to tell from the spelling exactly what the function does, they don't need to understand the implementation to work on the code. I think named lambdas will become more and more popular. Python's completely wrong on lambdas imo. My proposed style is: More aggressively extracting functions (making the code more readable from good spellings) + More aggressively inlining the function implementations (trading off readability in the current scope for that outside) – Tom Huntington Jan 27 '23 at 07:02