lists of variables

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sat Feb 20 23:21:09 EST 2010


On Sat, 20 Feb 2010 21:25:19 -0600, Michael Pardee wrote:

> I'm relatively new to python and I was very surprised by the following
> behavior:
[snip]

I don't see why. It's fairly unusual behaviour to want, and it would be 
surprising if you did this:

def test():
    x = 1
    mylist = [2, 4, x]
    function(mylist)
    assert x == 1

and the assertion failed, even though you never passed x to the function. 
Such behaviour could easily turn into a never-ending source of bugs.


> So it looks like variables in a list are stored as object references.

Python doesn't store variables in lists, it stores objects, always.

Even Python variables aren't variables *grin*, although it's really 
difficult to avoid using the term. Python variables are mappings between 
names (strings) and objects, not memory locations.


> So I figure my initial example doesn't work because if you assign a
> literal to something it is changing the object.  But modifying a list or
> dict (as long as you don't re-construct it) does not change the object.

Yes, we talk about name binding (and rebinding) versus mutation. A simple 
example:

>>> alist = blist = []  # bind two names to the same list object
>>> alist.append(1)  # mutate the list (modify in place)
>>> blist
[1]


>>> alist = alist + [2]  # a rebinding operation
>>> blist
[1]
>>> alist
[1, 2]


> I can think of some ways to work around this, including using single
> element lists as "pointers":

Yes, that's a standard way to do it, except that by "standard" I mean 
"really really really rare, honestly, hardly anyone does that".

Slightly less rare, but still uncommon, is to wrap objects in an instance:

class Record:
    pass

o = Record()
o.x = 1
o.y = 2
modify(o)
print o.x, o.y

Of course you can make the class as fancy, or as simple, as you want.

But a better approach is to take advantage of Python's ability to return 
multiple values:

x = 1
y = 2
x, y = modify(x, y)

rather than:

x = 1
y = 2
modify([x, y])


Speaking as an old Pascal coder, you won't miss pass-by-reference very 
often.




-- 
Steven



More information about the Python-list mailing list