Purify- Why is my for loop stopping at the first even integer


#1




My code is stopping as soon as it prints out the first even integer, i'm assuming it's because of where my "return" statement is place.

The problem is, as soon as I move it, or rather adjust the indentation level, I get an error as well. Without moving it the error I get is:

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

Can anyone help? I sort of understand what the error is saying but I'm not sure how to fix it, I'm stumped.


def purify(x):
    new_list =[]
    for i in x:
        if i % 2 == 0:
           print(i)
           new_list = new_list.append(i)
           return i
    print (new_list)
print(purify([1,2,3,4]))


#2

If fixing one bug reveals another, then you should still fix the first one, right? And then start investigating the new one.


#3

Right, that's what I was trying to do, which is why I changed the indentation level of the "return i" statement to be directly under for, so it'd allow the for loop to run through the entire list.

And it printed out 2 and 4, however I still got an error, as I tested it by adding 6 at the end of the list, and now it stops at 4 and gives me this error:
Your code looks a bit off--it threw a "'NoneType' object has no attribute 'append'" error. Check the Hint if you need help!

I'm not sure what it means or what it's referring to by "NoneType" object has no attribute. I mean I can only speculate what that error might be getting at. I suppose it's saying "i" has no attribute. Though I would think python would recognize "i" as all the items in the list?


#4

NoneType is a type, it has a single instance and that value is None
That value represents lack of value, it is for example returned by functions that do not have an explicit return value

The error message mentions append, and you're only using that in one place. What it says you're doing is:

None.append

Running that looks like so, note that it's the same error message:

>>> None.append
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'append'

Which tells you that new_list has the value None
If you expect it to have some other value at that point in time then you'll need to look at what was last assigned to it, as evidently it's not it's referring to what you intend for it to refer to


#5

Ah I see, I just had an inaccurate idea of what it was referring to. It would make sense as new_list doesn't have any value assigned at the start of the function. Thanks for clarifying that for me, I hate to heckle people for answers but I'm still a beginner with lots of questions so I appreciate the patience and help.

So I fixed it, making the following changes below and it prints all the even numbers into a new_list.
BUT, Code academy is still saying there's an error despite all the even number being printed out into the list?

def purify(x):
    new_list = []
    for i in x:
        if i % 2 == 0:
           print(i)
           new_list.append(i)
    print (new_list)
print(purify([1,2,3,4,6,8,10]))

I don't have any idea why it'd still be giving me this error if it's doing what it's supposed to?
Your function crashed on [1] as input because your function throws a "'NoneType' object is not iterable" error.


#6

Idk about that, what does the first line of the function do?

Reproduce that, get the line number, add prints to find out what was going on right before.
I can't reproduce that, so maybe there's something wrong about that observation or how you ran your code


#7

Oh yeah sorry excuse the brain fart, I'm assigning it to an empty list on the first line of the function.
Also, turns out all I had to do was write return(new_list) instead of print? It's always the little things hmmm...


#8

Printing and returning are two entirely different things, what happened there was you saw the correct output, but the behaviour still wasn't right. If it "looks right" but isn't, then test the behaviour. Assumptions are useful but conditional, and keeping track of that condition is something humans struggle with and that leads to things not adding up and one ends up getting stuck and frustrated.

List's append method doesn't return anything, yet you were using its return value.


#9

Also, the "NoneType is not iterable thing", that was a bug in the submission test. It tried to sort your result, but it was None and that doesn't meet the properties that the sort function used requires.

>>> sorted(purify([1]))
[]                    <--- note this was printed
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not iterable

      ^ and then the return value failed to be sorted

#10

Yeah I definitely struggle when it comes to discerning the difference between Printing and Returning, that's something I need to work on. But I suppose that's why Code academy wants things done a certain way so we can pick up on that. So would it be accurate to say return is a better way to go rather than print? Or is it subjective/does it depend on what you're going for.


#11

Functions should generally not print anything unless it's explicitly their purpose

For example, say you have a function that adds two numbers together, and you want to add 1, 1, and 1 (three ones) - you would call the function once for two of them, and then again with the result and the last one. If the result was printed, then you wouldn't be able to do that, kind of useless.

>>> add(add(1, 1), 1) # 3

If you have a function like what you may have encountered in math classes (grade 10 ish?)
f(x) = x + 1, then f(3) evaluates into a value. What if it printed instead? That would be gross misbehaviour


#12

So essentially 'return' stores the result so the function could access that result (2 for the first two ones), and add that result to the third one? While print just prints out the result, not giving the function the ability to call back on that result later?


#13

What happens much closer to the hardware level than Python is concerned, is that the return value is pushed to the stack and then execution jumps back to where the function was called, the caller can then find the return value at the top of the stack

Printing would instead call some other procedure which makes things appear on some monitor, this is pretty much going rogue unless the caller asked for it, a slow and unwanted side-effect. And if it doesn't then leave the result on top of the stack as it returns, then the caller has no access to that.

Computer memory is like an array (in some languages arrays are addresses to memory, though the OS is still adding a layer of abstraction first). Executing code is to loop from a location and executing an instruction one at a time. Some of those are to jump to other locations.

The stack is like a pile of values where only the location of the top value is kept track of. Adding something means to move the address one step, removing is to move the address in the other direction one step. To get the 5th value from the top, you start at the top and count 5 steps down and there's your value. This is how computers keep track of function calls and also the local variables in each function call, all piled up on a stack. Other values are instead stored wherever there's free room, and and address to where that is gets stored in on the stack. Useful for carrying values between function calls, particularly large ones.

A less technical analogy is if you ask me the time and I go tell Bob the time and then return to you saying nothing. It's just kind of rude isn't it.


#14

Way-way-way overcourse. But also very good to know and you seem to have a head on your shoulders. It's okay if this doesn't entirely sink in yet, it's good to just get exposed to it anyway.


#15

No, no, you're fine, I welcome it! I'm taking a computer science class at my school at the moment, so any help I can get to learn how programs/coding/computers access and store data is helpful. Very interesting read and I enjoyed that analogy haha.

Also, I can confirm that I indeed have a head on my shoulders lol, you heard it here first folks haha.
It's always a good thing to get more information than not enough in my opinion.


#16

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.