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

自定义MERFISH_tools类中__next__魔法方法未调用原因排查

问题

尝试通过定义__iter__和__next__方法让自定义类MERFISH_tools可迭代,需求是:

  • 当存在指定数据子集索引的fov_list时,用yield语句迭代对应值;
  • 当fov_list为空时,让__iter__返回类实例,通过调用__next__遍历全部数据直到触发StopIteration异常。

目前已经用其他方法解决问题,但疑惑:为什么fov_list为空时__next__方法没被调用?是不是yield语句影响了__next__的功能?

相关代码如下:

class MERFISH_tools():

    def __init__(self):
        self.fov_list = []
        FOV_list_path = os.path.join(os.path.dirname(os.path.dirname(config.get("merlin_folder"))),"analysis_parameters","fov_list","fov_list.txt")
        if os.path.exists(FOV_list_path):
            with open(FOV_list_path) as f:
                self.fov_list = [int(fov.strip() for fov in f.readlines()]  # 原代码存在语法错误

    def __iter__(self):
        if len(self.fov_list) == 0:
           self.i = 0
           return self
        else:
           for fov in self.fov_list:
               yield fov,self[fov]

    def __next__(self) -> tuple:
        i = self.i
        self.i +=1
        if self.i > self.positions.positions.shape[0]:
            raise StopIteration
        return i,self[i]
分析与解答

问题根源:语法错误+迭代器分支逻辑的触发问题

你遇到__next__未被调用的情况,核心是两个点:

  1. 原代码的语法错误
    原代码中int(fov.strip() for fov in ...)少了一个闭合括号,正确写法是int(fov.strip())。这个错误会导致初始化阶段直接抛出异常,fov_list无法被正确赋值为空列表,自然走不到__iter__返回自身的分支,__next__也就没机会被调用。

  2. 迭代器协议的分支独立性
    就算修复了语法错误,你要明确:__iter__在fov_list非空时返回的是生成器对象(因为用了yield),生成器自带__next__逻辑,和类定义的__next__无关;而空列表时返回类实例,才会触发你写的__next__方法。这两个分支是完全独立的,互不干扰。

关于yield是否影响__next__?

明确说:yield不会影响类的__next__功能。yield只是让__iter__返回一个生成器,生成器的迭代逻辑由yield语句完全控制;当__iter__返回类自身时,Python才会调用你定义的__next__方法——两者没有互相覆盖或干扰的关系。

修正后的可行代码示例

如果要保留原需求的两种迭代方式,修正语法和细节后的代码如下:

import os
# 假设config和positions已正确定义

class MERFISH_tools():

    def __init__(self):
        self.fov_list = []
        FOV_list_path = os.path.join(
            os.path.dirname(os.path.dirname(config.get("merlin_folder"))),
            "analysis_parameters", "fov_list", "fov_list.txt"
        )
        if os.path.exists(FOV_list_path):
            with open(FOV_list_path) as f:
                # 修复语法错误:补充int()的闭合括号
                self.fov_list = [int(fov.strip()) for fov in f.readlines()]
        # 确保self.positions已正确初始化
        self.positions = ...  

    def __iter__(self):
        if self.fov_list:  # 更简洁的非空判断方式
            for fov in self.fov_list:
                yield fov, self[fov]
        else:
            self.i = 0
            return self

    def __next__(self) -> tuple:
        current_i = self.i
        self.i += 1
        # 修正判断条件:避免索引越界(索引从0开始,用>=判断更合理)
        if current_i >= self.positions.positions.shape[0]:
            raise StopIteration
        return current_i, self[current_i]
    
    # 必须实现__getitem__方法,否则self[fov]会触发异常
    def __getitem__(self, idx):
        # 这里编写根据索引获取对应数据的逻辑
        return ...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 21:31:17