为什么我会收到此错误?类型错误:iter() 返回类型为“NoneType”的非迭代器

VRM*_*VRM 3 python iteration

我正在尝试学习 __iter__ 方法,这是我收到的错误:

print(i for i in my_iter)
TypeError: iter() returned non-iterator of type 'NoneType'
Run Code Online (Sandbox Code Playgroud)

我的代码如下:

class IterMethod:
    def __init__(self, last_elem):
        pass

    def __iter__(self):
        i = 5
        while i <= 50:
            print(f"this is {i}")
            i = i + 10
    
my_iter = IterMethod(60)

print(i for i in my_iter)
Run Code Online (Sandbox Code Playgroud)

你能解释一下为什么吗?谢谢!

ewo*_*okx 6

(抱歉,在我急于提供答案时,我没有解释为什么会出现错误。此编辑是为了包括解释。)

解释:

TypeError: iter() returned non-iterator of type 'NoneType' 意味着__iter__()不返回任何值(默认情况下,这意味着“无返回值”(在本例中)为 None )。(令人困惑,我知道这意味着它在技术上返回 None 。)

__iter__每次从函数内“生成”一个值时都必须返回一个值。如果它不返回值,您会收到错误。

请注意,当我说的时候return a value,你不使用return. 对于iter (基本上是一个生成器函数),您需要使用yield. 如果您对此感到困惑,请阅读什么是生成器。即https://www.geeksforgeeks.org/generators-in-python/(例如,不隶属于此链接)。

所以...

两个问题加一项更改(如 @DanielWalker 的建议):

  1. 您可以通过更改来使其更简单:
   i = i + 10
Run Code Online (Sandbox Code Playgroud)

   i += 10
Run Code Online (Sandbox Code Playgroud)
  1. 你需要改变你的print(i for i in my_iter).

这样就打印了生成器签名。你想要的是:

   print(list(i for i in my_iter))
Run Code Online (Sandbox Code Playgroud)
  1. 您需要yield在您的方法中有一个声明__iter__

根据您是否想要i该值,您有以下选项:

class IterMethod:
    def __init__(self, last_elem):
        pass

    def __iter__(self):
        i = 5
        while i <= 50:
            print(f"this is {i}")
            i += 10
            yield i


my_iter = IterMethod(60)

print(list(i for i in my_iter))
Run Code Online (Sandbox Code Playgroud)

所以这将输出:

this is 5
this is 15
this is 25
this is 35
this is 45
[15, 25, 35, 45, 55]
Run Code Online (Sandbox Code Playgroud)

现在如果你想产生i之前的值i = i + 10

class IterMethod:
    def __init__(self, last_elem):
        pass

    def __iter__(self):
        i = 5
        while i <= 50:
            print(f"this is {i}")
            yield i
            i += 10


my_iter = IterMethod(60)

print(list(i for i in my_iter))
Run Code Online (Sandbox Code Playgroud)

这将输出:

this is 5
this is 15
this is 25
this is 35
this is 45
[5, 15, 25, 35, 45]
Run Code Online (Sandbox Code Playgroud)