indirectly addressing vars in Python

Lie Ryan lie.1296 at gmail.com
Wed Oct 1 12:15:37 EDT 2008


On Wed, 01 Oct 2008 10:53:08 -0400, Ross wrote:

> Forgive my newbieness - I want to refer to some variables and indirectly
>   alter them.  Not sure if this is as easy in Python as it is in C.
> 
> Say I have three vars: oats, corn, barley
> 
> I add them to a list: myList[{oats}, {peas}, {barley}]
> 
> Then I want to past that list around and alter one of those values. That
> is I want to increment the value of corn:
> 
> myList[1] = myList[1] + 1
> 
> Is there some means to do that?.   Here's my little session trying to
> figure this out:
> 
>  >>> oats = 1
>  >>> peas = 6
>  >>> myList=[]
>  >>> myList
> []
>  >>> myList.append(oats)
>  >>> myList
> [1]
>  >>> myList.append(peas)
>  >>> myList
> [1, 6]
>  >>> myList[1]= myList[1]+1
>  >>> myList
> [1, 7]
>  >>> peas
> 6
>  >>>
>  >>>
> So I don't seem to change the value of peas as I wished.  I'm passing
> the values of the vars into the list, not the vars themselves, as I
> would like.
> 
> Your guidance appreciated...
> 
> Ross.

Short answer: Python is not C.

Long answer: In python, integers are immutable (they do not change), i.e. 
if you do:
a = 1
b = 2
c = a + b
 
a + b creates a new integer object that has the value 3 and assign it to c

Other examples of immutable values are: number types, string, tuple, etc.

In python, "variable" is usually called "name". The concept of variable 
and name is slightly different.

In C, a variable contains an object. In python, a name contains a pointer 
to an object. (the term "pointer" is used a bit loosely here)

In python, a "list" is a list of pointers to objects.

i.e.:

       |--> "Hello World"
myList |--> 1
       |--> 6

when you do, for example, myList[2] + 1
what you're doing is:
1. fetch the value of myList[2] (i.e. 6)
2. do an arithmetic addition of 6 + 1
3. create a new integer object with value 7
4. bind myList[2] to that new integer object (_new integer object_ since 
integer is immutable, you cannot change its value[1])

in short, pea is left intact since pea points to integer object 6.

beware though, that things are different if myList[2] is a mutable value 
instead and the operation is an in-place operation, e.g. list.sort

>>> a = [1, 2]
>>> b = [3, 2]
>>> myList.append(a)
>>> myList.append(b)
>>> myList[1].sort()
>>> myList
[[1, 2], [2, 3]]
>>> b
[2, 3]

in this case a, b is mutable object, so:
myList.append(x) binds myList to the list object pointed by x
myList[1].sort() is an in-place sort to the list object [3, 2] (i.e. it 
mutates the list [3, 2] instead of creating a new list[1]).

in this case:

myList |--> [1, 2]
       |--> [3, 2]

myList[1].sort(), being an in-place sort, modifies the list object [3, 2] 
in-place. Since b points to the same list object, b's list is changed too.

To summarize, you don't usually use that line of thinking in python. If 
you really insists, though is not pythonic (and is really absurd anyway), 
you may use this:

>>> a = [1]
>>> b = [2]
>>> myList.append(a)
>>> myList.append(b)
>>> myList[1][0] = myList[1][0] + 1
>>> myList
[[1], [2]]
>>> b
[3]

[1] Well, not always though, in CPython (the standard python reference 
implementation), small immutable values are cached as speed optimization. 
This is a safe operation, except for identity testing. But that doesn't 
matter much, since identity testing of immutable is moot.
[2] If you want a sorting operation that returns a new list, use sorted
(list)




More information about the Python-list mailing list