skip to navigation
skip to content

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 pairwise an iterable, like "ABCD", and pairwise gives 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.


  1. 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.

Systems Automation in Python

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.

.quiz-container { font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; max-width: 900px; margin: 2rem auto; padding: 1.25rem; } .meta { text-align: center; color: #555; margin-bottom: 1.25rem; } .progress-wrap { background:#eee; border-radius:999px; overflow:hidden; height:14px; margin-bottom:1rem; box-shadow: inset 0 1px 2px rgba(0,0,0,0.03); } .progress-bar { height:100%; width:0%; transition: width 450ms cubic-bezier(.2,.8,.2,1); background: linear-gradient(90deg,#4f46e5,#06b6d4); } .question { background:#fbfdff; border:1px solid #eef2ff; padding:14px; border-radius:12px; margin-bottom:14px; box-shadow: 0 1px 2px rgba(13,17,25,0.03); } .q-head { display:flex; justify-content:space-between; align-items:center; gap:12px; } .q-num { background:#eef2ff; color:#3730a3; padding:6px 10px; border-radius:999px; font-weight:600; font-size:0.9rem; } .options label { display:block; margin:8px 0; padding:8px 10px; border-radius:8px; cursor:pointer; transition: background 180ms, transform 120ms; } .options input { margin-right:8px; } .options label:hover { transform: translateY(-2px); } .correct { background: #ecfdf5; border:1px solid #bbf7d0; } .incorrect { background: #ffefef; border:1px solid #fca5a5; } .muted { color:#666; font-size:0.9rem; } .controls { display:flex; gap:12px; justify-content:flex-end; align-items:center; margin-top:12px; } button.primary { background:#4f46e5; color:white; border:none; padding:10px 16px; border-radius:10px; cursor:pointer; font-weight:600; } button.ghost { background:transparent; border:1px solid #e5e7eb; padding:8px 12px; border-radius:10px; cursor:pointer; } #result { margin-top:16px; font-size:1.05rem; font-weight:700; text-align:center; } .explanation { margin-top:8px; font-size:0.95rem; color:#0f172a; } .fade-in { animation: fadeIn 380ms ease both; } @keyframes fadeIn { from { opacity:0; transform: translateY(6px);} to {opacity:1; transform:none;} } Progress
Answered 0 of 15
1
Which of the following best describes a z-score?
2
What is the main advantage of using tidy data principles in R?
3
In Python, which library is most commonly used for data manipulation?
4
Which metric is best for evaluating a classification model on imbalanced data?
5
In a linear regression, what does R² represent?
6
In historical or humanities datasets, which challenge occurs most frequently?
7
What does the groupby() function do in pandas?
8
What is the primary purpose of cross-validation?
9
Feature engineering refers to:
10
Which visualization is most appropriate for the distribution of a continuous variable?
11
A z-score of +2.5 means:
12
Which is an advantage of using R for statistical analysis?
13
Normalization in data preprocessing means:
14
Why may historical datasets be biased?
15
Which Python function can compute a z-score?

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

CVSS v3.0 Base Score: 6.5

Workaround

There is no workaround.

Resolution

All affected users should upgrade trytond to the latest version.

Affected versions per series:

Non affected versions per series:

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

Read full topic

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

CVSS v3.0 Base Score: 7.3

Workaround

There is no general workaround.

Resolution

All affected users should upgrade sao to the latest version.

Affected versions per series:

Non affected versions per series:

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

Read full topic

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

CVSS v3.0 Base Score: 7.1

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:

Non affected versions per series:

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

Read full topic

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

CVSS v3.0 Base Score: 4.3

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:

Non affected versions per series:

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

Read full topic

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?

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:

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!

59%

Of our US $300,000.00 goal for 2025, as of November 19th, 2025, we are at:

  • 58.7% funded
  • $176,098.60 donated

Donate to support Django

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 […]

November 19, 2025 01:40 PM UTC