12/15 purify using remove()


#1
def purify(nums):
  newnums = nums
  for x in nums:
    if x % 2 != 0:
      nums.remove(X)
  return newnums

Hey guys, I’ve seen a few posts about how using remove() is the harder way, it makes it more complicated, etc., and I totally get it. However, what I don’t understand is why my code doesn’t work. I anticipated problems with modifying the same list that you’re iterating through, and I was following the directions, so I created a new identical list called “newnums”. No matter how many times I think it through, I just think it should work. However, it always tells me it returns (4,5,4) when it is called with (4,5,5,4), which is the exact same error you get if you iterate through and modify the same list.

Why? This is driving me insane. It defies logic as far as I can see.

Thanks :slight_smile:


#2

Consider the object you are iterating. Should you be mutating it during that operation?


#3

In other words that isn’t what you are doing


#4

No, which is why I copied it into a new object called newnums, which is being modified. I iterate through nums without modifying it.

Or are you saying that’s the problem?


#5

newnums and nums both point to the same object. To be sure you have a discrete copy, take a slice…

newnums = nums[:]

or,

newnums = nums.copy()

#6

So you’re saying that using = to set a variable equal to some object is more like making it a pronoun for that object? (to use a grammatical analogy) I was under the impression that it created a new, initially identical, object which could then be modified with impunity.


#12

Assignment changes what a variable refers to. That’s all it does.
To assign to a new value, you have to separately create that value first.

everything in python is by reference. The actual storage is somewhere else, inaccessible. Values are removed when they are no longer referred to.

But even if assignment did make a copy, which it doesn’t, your code is using the same variable when iterating and modifying, so it’s doubly wrong

And, since your code makes no operations on your newnums variable, you’ve already shown that assignment doesn’t do a copy because if a copy was made and you made no modifications to that copy, then you’d be returning a value identical to the input

Another thing is that list.remove isn’t suitable for removing multiple values because that involves a lot of moving (you need to know what things actually do when you use them)

The only suitable solution is to create a new list with the values to keep.
One could alternatively keep two locations, one where you read and one where you write, so you’d write the values back into the same list. This would be in-place, and it’s something you might see in a language like C, but it makes no meaningful difference in python, and if you cared about it then 1) it’s hard to say whether it’s faster or slower 2) you’re using the wrong language

# this is arguably not python at all

def purify(items):
    read = write = 0
    stop = len(items)
    while read != stop:
        item = items[read]
        read += 1
        if item % 2 == 1:
            items[write] = item
            write += 1
    # resize the list, eliminating junk left past what was written
    del items[write:]


data = list(range(10))
print(data)
purify(data)
print(data)

And even in languages you would do this, it’s probably mostly because of the limitations of that language, where it’s difficult to allocate new memory and to give ownership of that memory to the caller of the function - so instead the caller has to send in a piece of memory to write in.
In python that ownership is held by python itself, the programmer doesn’t need to care. And, the list doesn’t contain the values anyway, it’s all just references. Python is very far removed from needing to write code this way.

But at least it does touch on something rather important when learning to program. Python’s actions do a lot, they are wide brushes, they behave very nicely. Learners sometimes make bad assumptions about how things behave. There’s no way to do that when the programmer is painstakingly pushing every single byte around.
For example, the remove method of list causes elements to move. A beginner might not stop and think about what removing does to a list. If they had to do the removing themselves, they would know exactly what it did.


#13

But even if assignment did make a copy, which it doesn’t, your code is using the same variable when iterating and modifying, so it’s doubly wrong

And, since your code makes no operations on your newnums variable, you’ve already shown that assignment doesn’t do a copy because if a copy was made and you made no modifications to that copy, then you’d be returning a value identical to the input

That’s true – I just realized I made a typo. In the original version it read: newnums.remove(X).

I see your point, and like I said I do understand why it’s better to use append here. I was just curious why it wouldn’t work using remove(). As for understanding exactly what functions do before I use them, all I can say is that I’m still learning – I think if I were at that level I wouldn’t need to be using the free Codecademy online introductory coursework.

Final question: If I made a copy like you said, and assuming I hadn’t made that typo, could I do this using remove()? And keep in mind I get that it’s inefficient / ugly etc. I’m just trying to do what you said: understand exactly what things do.


#14

If you iterate over the object from the right side, moving left, any element you remove will be behind the pointer’s next position. In such a case you would not need two lists.


#15

I’d argue that question has nothing to do with python. Removing something until it’s no longer there will make it gone, right.
And I’d further argue that whenever you plan something out, that you’re thinking in terms of concepts, not a language. The language is for describing what you’ve already decided on.

…And that’s where the ugliness comes in. You’d probably never decide to do this. You’d decide on something else, and that’s what you should write in code!

If you had a list on paper. How would you do it? Do that.


#16

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