我正在尝试学习 __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)
你能解释一下为什么吗?谢谢!
(抱歉,在我急于提供答案时,我没有解释为什么会出现错误。此编辑是为了包括解释。)
解释:
这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 的建议):
i = i + 10
Run Code Online (Sandbox Code Playgroud)
到
i += 10
Run Code Online (Sandbox Code Playgroud)
print(i for i in my_iter).这样就打印了生成器签名。你想要的是:
print(list(i for i in my_iter))
Run Code Online (Sandbox Code Playgroud)
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)