Planet Python
Last update: November 25, 2025 01:44 AM UTC
November 24, 2025
Rodrigo Girão Serrão
Generalising itertools.pairwise
In this article you will learn about itertools.pairwise, how to use it, and how to generalise it.
In this tutorial you will learn to use and generalise itertools.pairwise.
You will understand what itertools.pairwise does, how to use it, and how to implement a generalised version for when itertools.pairwise isn't enough.
itertools.pairwise
itertools.pairwise is an iterable from the standard module itertools that lets you access overlapping pairs of consecutive elements of the input iterable.
That's quite a mouthful, so let me translate:
You give
pairwisean iterable, like"ABCD", andpairwisegives you pairs back, like("A", "B"),("B", "C"), and("C", "D").
In loops, it is common to unpack the pairs directly to perform some operation on both values.
The example below uses pairwise to determine how the balance of a bank account changed based on the balance history:
from itertools import pairwise # Python 3.10+
balance_history = [700, 1000, 800, 750]
for before, after in pairwise(balance_history):
change = after - before
print(f"Balance changed by {change:+}.")
Balance changed by +300.
Balance changed by -200.
Balance changed by -50.
How to implement pairwise
If you had to implement pairwise, you might think of something like the code below:
def my_pairwise(iterable):
for prev_, next_ in zip(iterable, iterable[1:]):
yield (prev_, next_)
Which directly translates to
def my_pairwise(iterable):
yield from zip(iterable, iterable[1:])
But there is a problem with this implementation, and that is the slicing operation.
pairwise is supposed to work with any iterable and not all iterables are sliceable.
For example, files are iterables but are not sliceable.
There are a couple of different ways to fix this but my favourite uses collections.deque with its parameter maxlen:
from collections import deque
from itertools import islice
def my_pairwise(data):
data = iter(data)
window = deque(islice(data, 1), maxlen=2)
for value in data:
window.append(value)
yield tuple(window)
Generalising itertools.pairwise
pairwise will always produce pairs of consecutive elements, but sometimes you might want tuples of different sizes.
For example, you might want something like “triplewise”, to get triples of consecutive elements, but pairwise can't be used for that.
So, how do you implement that generalisation?
In the upcoming subsections I will present different ways of implementing the function nwise(iterable, n) that accepts an iterable and a positive integer n and produces overlapping tuples of n elements taken from the given iterable.
Some example applications:
nwise("ABCD", 2) -> ("A", "B"), ("B", "C"), ("C", "D")
nwise("ABCD", 3) -> ("A", "B", "C"), ("B", "C", "D")
nwise("ABCD", 4) -> ("A", "B", "C", "D")
Using deque
The implementation of pairwise that I showed above can be adapted for nwise:
from collections import deque
from itertools import islice
def nwise(iterable, n):
iterable = iter(iterable)
window = deque(islice(iterable, n - 1), maxlen=n)
for value in iterable:
window.append(value)
yield tuple(window)
Note that you have to change maxlen=2 to maxlen=n, but also islice(iterable, 1) to islice(iterable, n - 1).
Using tee
Another fundamentally different way of implement nwise is by using itertools.tee to split the input...
November 24, 2025 06:36 PM UTC
EuroPython Society
New Europython Society Fellow in 2025
A warm welcome to Martin Borus as the second elected EuroPython Society Fellow in 2025.
EuroPython Society Fellows
EuroPython Society Fellows have contributed significantly towards our mission, the EuroPython conference and the Society as an organisation. They are eligible for a lifetime free attendance of the EuroPython conference and will
November 24, 2025 05:58 PM UTC
Trey Hunner
Python Black Friday & Cyber Monday sales (2025)
November 24, 2025 04:00 PM UTC
Nicola Iarocci
Flask started as an April Fool's joke
The story that the Python micro web framework Flask started as an April Fool’s joke is well known in Python circles, but it was nice to see it told by Armin Ronacher himself1.
I’m fond of Flask. It was a breath of fresh air when it came out, and most of my Python open-source work is based on it.
-
The video is produced by the people who also authored the remarkable Python: The Documentary. ↩︎
November 24, 2025 02:29 PM UTC
Real Python
How to Properly Indent Python Code
Learn how to properly indent Python code in IDEs, Python-aware editors, and plain text editors—plus explore PEP 8 formatters like Black and Ruff.
November 24, 2025 02:00 PM UTC
Python Software Foundation
Python is for Everyone: Grab PyCharm Pro for 30% off—plus a special bonus!
November 24, 2025 10:44 AM UTC
Python Bytes
#459 Inverted dependency trees
Topics include PEP 814 – Add frozendict built-in type, Material for MkDocs Zensical, Tach, and.
November 24, 2025 08:00 AM UTC
Zato Blog
Automation in Python
Automation in Python
How to automate systems in Python and how the Zato Python integration platform differs from a network automation tool, how to start using it, along with a couple of examples of integrations with Office 365 and Jira, is what the latest article is about.
➤ Read it here: Systems Automation in Python.
More resources
➤ Python API integration tutorials
➤ What is an integration platform?
➤ Python Integration platform as a Service (iPaaS)
➤ What is an Enterprise Service Bus (ESB)? What is SOA?
➤ Open-source iPaaS in Python
November 24, 2025 03:00 AM UTC
November 22, 2025
Daniel Roy Greenfeld
TIL: Default code block languages for mkdocs
Really useful for making inline code examples have code highlighting.
November 22, 2025 12:08 PM UTC
Brett Cannon
Should I rewrite the Python Launcher for Unix in Python?
I want to be upfront that this blog post is for me to write down some thoughts that I have on the idea of rewriting the Python Launcher for Unix from Rust to pure Python. This blog post is not meant to explicitly be educational or enlightening for others, but
November 22, 2025 12:18 AM UTC
Bruno Ponne / Coding The Past
Data Science Quiz For Humanities
Test your skills with this interactive data science quiz covering statistics, Python, R, and data analysis.
November 22, 2025 12:00 AM UTC
Stéphane Wirtel
Claude Code : comment un assistant IA m'a fait gagner des jours de développement
TL;DR
Après une semaine d’utilisation intensive de Claude Code1 pendant PyCon Ireland et sur mes projets personnels, je suis complètement bluffé par les gains de productivité. L’outil m’a permis de migrer automatiquement le site Python Ireland de Django 5.0 vers 5.2 et Wagtail 6.2 vers 7.2, de développer un outil de conversion de livres scannés en 5 minutes, et de générer une documentation complète en quelques minutes. Contrairement à Cursor ou Windsurf, Claude Code s’intègre partout (PyCharm, VS Code, Zed, Neovim, ligne de commande), ce qui en fait un véritable game changer pour les développeurs professionnels.
November 22, 2025 12:00 AM UTC
Armin Ronacher
LLM APIs are a Synchronization Problem
November 22, 2025 12:00 AM UTC
November 21, 2025
Trey Hunner
Python Morsels Lifetime Access Sale
November 21, 2025 10:42 PM UTC
Tryton News
Security Release for issue #14366
Cédric Krier has found that trytond does not enforce access rights for data export (since version 6.0).
Impact
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: Low
- User Interaction: None
- Scope: Unchanged
- Confidentiality: High
- Integrity: None
- Availability: None
Workaround
There is no workaround.
Resolution
All affected users should upgrade trytond to the latest version.
Affected versions per series:
trytond:- 7.6: <= 7.6.10
- 7.4: <= 7.4.20
- 7.0: <= 7.0.39
- 6.0: <= 6.0.69
Non affected versions per series:
trytond:- 7.6: >= 7.6.11
- 7.4: >= 7.4.21
- 7.0: >= 7.0.40
- 6.0: >= 6.0.70
Reference
Concerns?
Any security concerns should be reported on the bug-tracker at https://bugs.tryton.org/ with the confidential checkbox checked.
1 post - 1 participant
November 21, 2025 03:00 PM UTC
Security Release for issue #14363
Abdulfatah Abdillahi has found that sao does not escape the completion values. The content of completion is generally the record name which may be edited in many ways depending on the model. The content may include some JavaScript which is executed in the same context as sao which gives access to sensitive data such as the session.
Impact
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: Low
- User Interaction: Required
- Scope: Unchanged
- Confidentiality: High
- Integrity: High
- Availability: None
Workaround
There is no general workaround.
Resolution
All affected users should upgrade sao to the latest version.
Affected versions per series:
sao:- 7.6: <= 7.6.10
- 7.4: <= 7.4.20
- 7.0: <= 7.0.39
- 6.0: <= 6.0.68
Non affected versions per series:
sao:- 7.6: >= 7.6.11
- 7.4: >= 7.4.21
- 7.0: >= 7.0.40
- 6.0: >= 6.0.69
Reference
Concerns?
Any security concerns should be reported on the bug-tracker at https://bugs.tryton.org/ with the confidential checkbox checked.
1 post - 1 participant
November 21, 2025 03:00 PM UTC
Security Release for issue #14364
Mahdi Afshar has found that trytond does not enforce access rights for the route of the HTML editor (since version 6.0).
Impact
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: Low
- User Interaction: None
- Scope: Unchanged
- Confidentiality: High
- Integrity: Low
- Availability: None
Workaround
A possible workaround is to block access to the html editor.
Resolution
All affected users should upgrade trytond to the latest version.
Affected versions per series:
trytond:- 7.6: <= 7.6.10
- 7.4: <= 7.4.20
- 7.0: <= 7.0.39
- 6.0: <= 6.0.69
Non affected versions per series:
trytond:- 7.6: >= 7.6.11
- 7.4: >= 7.4.21
- 7.0: >= 7.0.40
- 6.0: >= 6.0.70
Reference
Concerns?
Any security concerns should be reported on the bug-tracker at https://bugs.tryton.org/ with the confidential checkbox checked.
1 post - 1 participant
November 21, 2025 03:00 PM UTC
Security Release for issue #14354
Mahdi Afshar and Abdulfatah Abdillahi have found that trytond sends the trace-back to the clients for unexpected errors. This trace-back may leak information about the server setup.
Impact
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: Low
- User Interaction: None
- Scope: Unchanged
- Confidentiality: Low
- Integrity: None
- Availability: None
Workaround
A possible workaround is to configure an error handler which would remove the trace-back from the response.
Resolution
All affected users should upgrade trytond to the latest version.
Affected versions per series:
trytond:- 7.6: <= 7.6.10
- 7.4: <= 7.4.20
- 7.0: <= 7.0.39
- 6.0: <= 6.0.69
Non affected versions per series:
trytond:- 7.6: >= 7.6.11
- 7.4: >= 7.4.21
- 7.0: >= 7.0.40
- 6.0: >= 6.0.70
Reference
Concerns?
Any security concerns should be reported on the bug-tracker at https://bugs.tryton.org/ with the confidential checkbox checked.
2 posts - 2 participants
November 21, 2025 03:00 PM UTC
Django Weblog
DSF member of the month - Akio Ogasahara
For November 2025, we welcome Akio Ogasahara as our DSF member of the month! ⭐
Akio is a technical writer and systems engineer. He contributed to the Japanese translation for many years. He has been a DSF member since June 2025. You can learn more about Akio by visiting Akio's X account and his GitHub Profile.
Let’s spend some time getting to know Akio better!
Can you tell us a little about yourself (hobbies, education, etc.)
I was born in 1986 in Rochester, Minnesota, to Japanese parents, and I’ve lived in Japan since I was one. I’ve been fascinated by machines for as long as I can remember. I hold a master’s degree in mechanical engineering. I’ve worked as a technical writer and a software PM, and I’m currently in QA at a Japanese manufacturer.
I'm curious, where does your nickname “libratech” come from?
I often used “Libra” as a handle because the symbol of Libra—a balanced scale—reflects a value I care deeply about: fairness in judgment. I combined that with “tech,” from “tech writer,” to create “libratech.”
How did you start using Django?
Over ten years ago, I joined a hands-on workshop using a Raspberry Pi to visualize sensor data, and we built the dashboard with Django. That was my first real experience.
What other framework do you know and if there is anything you would like to have in Django if you had magical powers?
I’ve used Flask and FastAPI. If I could wish for anything, I’d love “one-click” deployment that turns a Django project into an ultra-lightweight app running on Cloudflare Workers.
What projects are you working on now?
As a QA engineer, I’m building Pandas pipelines for quality-data cleansing and creating BI dashboards.
What are you learning about these days?
I’m studying for two Japanese certifications: the Database Specialist exam and the Quality Control Examination (QC Kentei).
Which Django libraries are your favorite (core or 3rd party)?
Django admin, without question. In real operations, websites aren’t run only by programmers—most teams eventually need CRM-like capabilities. Django admin maps beautifully to that practical reality.
What are the top three things in Django that you like?
- Django admin
- Strong security
- DRY by design
You have contributed a lot on the Japanese documentation, what made you contribute to translate for the Japanese language in the first place?
I went through several joint surgeries and suddenly had a lot of time. I’d always wanted to contribute to open source, but I knew my coding skills weren’t my strongest asset. I did, however, have years of experience writing manuals—so translation felt like a meaningful way to help.
Do you have any advice for people who could be hesitant to contribute to translation of Django documentation?
Translation has fewer strict rules than code contributions, and you can start simply by creating a Transifex account. If a passage feels unclear, improve it! And if you have questions, the Django-ja translation team is happy to help on our Discord.
I know you have some interest in AI as a technical writer, do you have an idea on how Django could evolve with AI?
Today’s AI is excellent at working with existing code—spotting N+1 queries or refactoring SQL without changing behavior. But code written entirely by AI often has weak security. That’s why solid unit tests and Django’s strong security guardrails will remain essential: they let us harness AI’s creativity safely.
Django is celebrating its 20th anniversary, do you have a nice story to share?
The surgeries were tough, but they led me to documentation translation, which reconnected me with both English and Django. I’m grateful for that path.
What are your hobbies or what do you do when you’re not working?
Outside of computers, I enjoy playing drums in a band and watching musicals and stage plays! 🎵
Is there anything else you’d like to say?
If you ever visit Japan, of course sushi and ramen are great—but don’t miss the sweets and ice creams you can find at local supermarkets and convenience stores! They’re inexpensive, come in countless varieties, and I’m sure you’ll discover a new favorite!🍦
Thank you for doing the interview, Akio !
November 21, 2025 01:00 PM UTC
Real Python
The Real Python Podcast – Episode #275: Building a FastAPI Application & Exploring Python Concurrency
What are the steps to get started building a FastAPI application? What are the different types of concurrency available in Python? Christopher Trudeau is back on the show this week, bringing another batch of PyCoder's Weekly articles and projects.
November 21, 2025 12:00 PM UTC
Armin Ronacher
Agent Design Is Still Hard
November 21, 2025 12:00 AM UTC
November 20, 2025
Brett Cannon
The varying strictness of TypedDict
I was writing some code where I was using httpx.get() and its params parameter. I decided to use a TypedDict for the dictionary I was passing as the argument since it was for a REST API, where the potential keys were fully known. I then ran Pyrefly over my
November 20, 2025 09:18 PM UTC
November 19, 2025
Django Weblog
Twenty years of Django releases
On November 16th 2005, Django co-creator Adrian Holovaty announced the first ever Django release, Django 0.90. Twenty years later, today here we are shipping the first release candidate of Django 6.0 🚀.
Since we’re celebrating Django’s 20th birthday this year, here are a few release-related numbers that represent Django’s history:
- 447 releases over 20 years. That’s about 22 per year on average. We’re at 38 so far for 2025. Fun fact: 33 of those releases predate PyPI, and were published via the Django website only!
- 131 security vulnerabilities addressed in those Django releases. Our security issues archive is a testament to our stellar track-record.
- 262,203 releases of Django-related packages. Django’s community ecosystem is gigantic. There’s tens of releases of Django packages per day as of 2025. There were 52 just today. With the caveat this depends a lot on what you classify as a "Django" package.
This is what decades’ worth of a stable framework looks like. Expect more gradual improvements and bug fixes over the next twenty years’ worth of releases. And if you like this kind of data, check out the State of Django 2025 report by JetBrains, with lots of statistics on our ecosystem (and there’s a Get PyCharm Pro with 30 % Off & Support Django offer).
Support Django
If you or your employer counts on Django’s 20 years of stability, consider whether you can support the project via donations to our non-profit Django Software Foundation.
Once you’ve done it, post with #DjangoBirthday and tag us on Mastodon / on Bluesky / on X / on LinkedIn so we can say thank you!
Of our US $300,000.00 goal for 2025, as of November 19th, 2025, we are at:
- 58.7% funded
- $176,098.60 donated
November 19, 2025 03:27 PM UTC
Real Python
Build a Python MCP Client to Test Servers From Your Terminal
Follow this Python project to build an MCP client that discovers MCP server capabilities and feeds an AI-powered chat with tool calls.
November 19, 2025 02:00 PM UTC
PyCharm
At JetBrains, we love seeing the developer community grow and thrive. That’s why we support open-source projects that make a real difference — the ones that help developers learn, build, and create better software together. We’re proud to back open-source maintainers with free licenses and to contribute to initiatives that strengthen the ecosystem and the […]
