You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python自定义迭代器类:两种__next__实现差异及临时变量必要性解析

Why do we need to store self.x in a variable in a custom iterator?

I'm trying to create a custom iterator using __iter__ and __next__ methods, and I came across this example code:

class OddNum:
    """Class to implement iterator protocol"""
    def __init__(self, num = 0):
        self.num = num
    def __iter__(self):
        self.x = 1
        return self
    def __next__(self):
        if self.x <= self.num:
            odd_num = self.x
            self.x += 2
            return odd_num
        else:
            raise StopIteration

for num in OddNum(10):
    print(num)

When I run this, the output is 1 3 5 7 9. But if I remove the line odd_num = self.x and change return odd_num to return self.x (so the __next__ method updates self.x before returning it), the output becomes 3 5 7 9 11.

I'm confused about the difference between these two implementations—why do we need to store self.x in a variable before returning it?


Great question! Let's break down the core difference between these two implementations: it all comes down to the order of operations when handling the iterator's state.

First Implementation (with odd_num = self.x)

Let's walk through the first call to __next__ step by step:

  1. We check if self.x (starting at 1) is ≤ self.num (10) — yes, it is.
  2. We save the current value of self.x (1) to odd_num. This preserves the value we want to return before modifying the iterator's state.
  3. We update self.x to 1 + 2 = 3, preparing it for the next iteration.
  4. We return odd_num (1), which is the correct odd number we wanted to yield.

This follows standard iterator behavior: return the current valid element first, then advance the iterator to the next position. Each subsequent call repeats this logic, so we get all odd numbers from 1 up to 9 (once self.x becomes 11, the next call triggers StopIteration).

Second Implementation (without storing the variable)

When you remove the odd_num variable and adjust the return statement, your __next__ method effectively becomes:

def __next__(self):
    if self.x <= self.num:
        self.x += 2
        return self.x
    else:
        raise StopIteration

Let's walk through this first call:

  1. self.x is 1, which is ≤ 10 — proceed.
  2. We immediately update self.x to 3 before returning anything.
  3. We return 3, skipping the initial value of self.x entirely.

On each subsequent call, we keep updating self.x first, then returning the new value. This leads us to yield 3, 5, 7, 9, and finally 11 (since when self.x is 9, it's still ≤ 10 — we update to 11 and return it, even though 11 > 10). The iterator only stops on the next call, when self.x is 11 and fails the check.

Why the variable matters

Storing self.x in a variable lets us decouple returning the current element from advancing the iterator. Without it, we can't access the original value of self.x once we've updated it — we end up skipping the first element and including an element that's outside our intended range (11 in this case).

This is a common pattern in iterators: you need to capture the state before modifying it to ensure you return the correct value for the current iteration.

内容的提问来源于stack exchange,提问作者rodny9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 12:07:31