The example I have in my code base was of a system that needed to process a list of images, chunk them into pairs, calculate the relationship of those pairs by passing it to a algorithm, returning the final results to a function that uploads them including the index of the pair which can be used to figure out which images were part of it whilst using tqdm to show the processing status.
Doing all of this without generators requires a large amount of hand written for loops which hurts readability since it’s less explicit
On top of this generators allowed us to lazily evaluate the list of items because we didn’t need to load or generate the images which has a cost
Unfortunately this presented two problems, it was easy to have bugs from the order of operations
pairs = windowed(images, 2)
pairs = map(process, pairs)
pairs = tqdm(pairs)
all_pairs = list(pairs)
pairs = enumerate(pairs)
return all_pairs
We can of course put this on one line to prevent line ordering bugs but you now need to read the methods right to left and balance brackets
all_pairs = list(enumerate(tqdm(map(process, windowed(images, 2)))))
So it’s difficult to maintain in another sense.
I would argue Python already has a construct that tries solve similar problems, list comprehension
Before it was introduced you similarly had to create the same logic across multiple lines
items =
for i in range(1,10):
if i % 2:
items.append(i)
Most languages decided to replace this pattern with functional programming, Python decided that it wasn’t a good fit for the language
Instead List comprehension turned that into something more readable and more maintainable by being able to build an array in one line
a = [i for i in range(1, 10) if i % 2]
But it still had some serious downsides, it executed immediately which made it difficult to handle iterating through large lists compared to hand rolled loops
The syntax was foreign compared to the functional programming people were used to from other languages.
And the syntax was both too limited for complex sequence generation logic and could still be hard to read when using more complex generation with nested arrays
[I for i in j for j in w for w in items]
And so Python took another step towards functional programming when they introduced generators and lambdas (to avoid predicates not being colocated with the statement it’s usd for)
x = list(filter(lambda i: i % 2, range(1, 10)))
So now we finally have a new way to build sequences that’s flexible enough to unlock new use cases without polluting the code with loads of for loops and callbacks for lazy evaluation
But we still haven’t quite cracked the readability as unfortunately the execution order is now in reverse, this is what the funnel operator or introducing a pipe object in functools could solve
x = range(1,10) |> filter(lambda i: i % 2) |> list()
Think of this as you will as “method call comprehension”
Python in many ways has crossed the functional programming bridge a while ago but in a way that allows teams to adopt how much functional programming they want
This concept would be the same, you can easily write the same code without needing to use it but the downside is the reverse call order I mentioned above
Just like you would have to drop down to for loops or list comprehension without the use of generators
Regarding readability like all concepts in Python you can find cases where they would be less readable and of course there are multiple ways of doing same thing in Python with different levels of readability and advantages & disadvantages
In your example I don’t think anyone would use it like that for I in enumerate(items) would be preferable and we can restrict the use of this operate in the for loops without expression to promote readability just like we do with list comprehension
Now I’m not sure about all of the syntax proposals but it feels like the ability to compose functions like this. Would be the final missing puzzle piece in a long history of Python slowly adopting more concepts to make it easy to work with streams
For example imagine this HTML DSL being used to construct a todo list of visible items
with html.ul() as list:
[list.append(html.li(item.text)) for item in items if item.visible]]
Would become:
with html.ul() as list:
list_items = items |> filter(lambda item: item.visible) |> map(lambda item: html.li(item.text))
[list.append(item) for item in list_items]
Essentially we get a nice way to declare reusable predicates
Em dom., 18 de mai. de 2025 às 18:45, Elis Byberi via Discussions on Python.org <[notifications@python1.discoursemail.com](mailto:Em dom., 18 de mai. de 2025 às 18:45, Elis Byberi via Discussions on Python.org < escreveu: