简体   繁体   中英

why am I getting this error? TypeError: iter() returned non-iterator of type 'NoneType'

I'm trying to learn the __iter__ method and this is the error I'm getting:

print(i for i in my_iter)
TypeError: iter() returned non-iterator of type 'NoneType'

My code is as follows:

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)

Can you please explain why? Thanks!

(My apologies, in my haste to provide an answer, I hadn't explained why there was an error. This edit is to include the explanation.)

Explanation:

The TypeError: iter() returned non-iterator of type 'NoneType' means that __iter__() wasn't returning any values (by default, this means it's None for "No return value" (In this particular case)). (Confusing, I know as that means it's technically returning None.)

__iter__ must return a value each time it 'generates' a value from within the function. If it doesn't return a value, you get the error.

Please note that when I say return a value , you don't use return . In the case of iter (which is basically a generator function), you need to use yield . If you're confused with this, please read up on what generators are. ie at https://www.geeksforgeeks.org/generators-in-python/ (for example, and not affiliated to this link).

So...

Two issues plus one change (as suggested by @DanielWalker):

  1. You could make it simpler by changing:
   i = i + 10

to

   i += 10
  1. You need to change your print(i for i in my_iter) .

As is this prints the generator signature. What you want is:

   print(list(i for i in my_iter))
  1. You need to have a yield statement in your __iter__ method.

Depending on if you want the i value to be, you have the following options:

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))

So this will output:

this is 5
this is 15
this is 25
this is 35
this is 45
[15, 25, 35, 45, 55]

Now if you want to yield the i value before the 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))

This will output:

this is 5
this is 15
this is 25
this is 35
this is 45
[5, 15, 25, 35, 45]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM