Python - "'NoneType' object is not iterable" error

15,320

Solution 1

The first problem is that you change the list while iterating over it. DO NOT change lists while you are iterating over them. You will miss out on some of the values in the loop.

The second problem is that list.remove acts in-place and returns None. Thus, when you do pure = pure.remove(num), you set pure to None, which is no longer iterable, which in turn is what causes the error. Instead, you can filter the list as follows

def purify(numbers):
    return [num for num in numbers if num % 2 == 0]

Solution 2

Well that error means that python is trying to iterate over a None object.

The only iteration in your code is your for loop, so pure must be the None.

Also, don't forget to indent properly:

def purify(numbers):

    pure = numbers

    for num in pure:
        if num % 2 != 0:
            pure = pure.remove(num)

    return pure

So pure is either being defined as None when you set it equal to numbers or it's being defined when you assign it from pure.remove(num). When you look up the documentation for remove(num), you see that it operates in-place, so it doesn't return anything useful (None usually). What you want to do it remove the pure = part in the for loop. You might notice that you end up skipping elements in your loop, but that would a separate problem with this piece of code (modifying something you're iterating over).

Share:
15,320
Jason T. Eyerly
Author by

Jason T. Eyerly

Updated on June 13, 2022

Comments

  • Jason T. Eyerly
    Jason T. Eyerly almost 2 years

    My instructions in a codecademy project are to

    Define a function called purify that takes in a list of numbers, removes all odd numbers in the list, and returns the result. For example, purify([1,2,3]) should return [2]. Do not directly modify the list you are given as input; instead, return a new list with only the even numbers.

    The code I have come up with is:

    def purify(numbers):
    
    pure = numbers
    
    for num in pure:
        if num % 2 != 0:
            pure = pure.remove(num)
    
    return pure
    

    And the error is:

    Oops, try again. Your function crashed on [1] as input because your function throws a "'NoneType' object is not iterable" error.

    As I've come to understand it, this means something in my code is being returned as "None". Or there is no data there. I can't seem to find what's wrong with this short and simple code, unless it's in my if statement. Thanks in advance.

    So I made the edit within the code to remove "pure = pure.remove(num)" and that solved the none issue. However, when running the code it still fails the input of [4,5,5,4] and returns [4,5,4].

    New Code:

    def purify(numbers):
    
        pure = numbers
    
        for num in pure:
            if num % 2 != 0:
                pure.remove(num)
    
        return pure
    
  • hlt
    hlt over 9 years
    You can also copy using pure = numbers[:] instead of using copy
  • Yoel
    Yoel over 9 years
    Yeah, I just now noticed that numbers is a list. Thanks :-)
  • Jason T. Eyerly
    Jason T. Eyerly over 9 years
    This is great. This is what I was looking for. Is this the filter function or list comprehension? I still don't grasp list comprehension which is why I ask. Thanks again!
  • hlt
    hlt over 9 years
    This is a list comprehension. It adds each item num from numbers to the new list (num for num in numbers), but only iff (that's a word) num is even (if num % 2 == 0).