If you're ever doing a foreach style iteration over a collection a la for object in objects:, object isn't a pointer or a reference, but a copy of what was in your collection. If you can remember this, you'll save yourself a couple hours of bashing your head on the wall and wondering where the hell your data was going
(
Read more... )
Now, you also have names that refer to these objects. There can be many different names that refer to the same object, and a name can refer to different objects at different times. When you perform assignment, or binding, you don't change the identity of any particular object, and you don't mutate any objects, you change which object a particular name points to. This is how the object variable in a loop like for object in objects works; it is a name that is assigned a different value in each iteration of the loop.
So, for instance, if you have something like the following, you will not actually modify the list; what you are doing is modifying which object thing points to:
list = [1, 2, 3]
for thing in list
thing = thing + 1
But if you have some objects, foo, bar, and baz that have some member called member, the following code will change each of the objects in the list, demonstrating that they are actually being manipulated by pointer/reference:
list = [foo, bar, baz]
for thing in list
thing.member = thing.member + 1
I'm assuming that you wanted something like the first example to modify the list itself. The way to do that in Python is:
for i in range(len(list))
list[i] = list[i] + 1
I think your confusion stems from thinking of lists in Python the way you think of arrays in C where items are inline, and you use a pointer to traverse the list. The thing is, in C, a pointer to one of the objects in the list is also a pointer to that location in the list, so if you modify the thing it points to, you're modifying that location in the list. In Python (and almost every other high-level language, like Java, Scheme, Ruby, Lisp), everything that's not atomic is passed around by pointer, and you get the pointer to the object itself in your iterators, not a pointer to the location in the collection.
Sorry for the lecture, I just wanted to make sure you didn't think a copy of the full object was happening in your iterator, since that would come back to bite you later when you assumed it wasn't being modified.
Reply
I had a collection of objects of class Field and subclasses thereof, and I was trying to do something like this:
for field in fields:
if field.name == 'foo': field = FieldSubclass(field.name)
It's obvious to me now why that wouldn't have done any good.
Thanks for the lecture though--I get it now. That's the problem with high-level languages like this. Since you don't have much direct control over memory yourself, you really have to know what's going on under the hood. Not that I have anything against knowing what's going on; it just makes for a slight learning curve every time you learn a new language, since it's usually a little different. I'm surprised I've managed to do as much in Python as I already have without running into this.
Reply
Leave a comment