[newbie] A question about lists and strings

Dave Angel d at davea.name
Fri Aug 10 06:07:50 EDT 2012


On 08/10/2012 05:19 AM, Mok-Kong Shen wrote:
>
> In an earlier question about lists, I was told about the issue of
> creation of local names in a function. However, I still can't
> understand why the program below outputs:
>
> [999] sss
> [999]
>
> and not two identical lines of output. For both operators "+=" should
> anyway work in similar manner in the function xx in my view.
>
> Thanks for your help in advance.
>
> M. K. Shen
>
> ----------------------------------------------------------
>
> def xx(list,str):
>   list+=[999]
>   str+="sss"
>
> lista=[]
> stra=""
> lista+=[999]
> stra+="sss"
> print(lista,stra)
>
> listb=[]
> strb=""
> xx(listb,strb)
> print(listb,strb)

I'm rewriting your xx function so it doesn't overwrite reserved words,
list and str.

def xx(mylist, mystring):
    mylist += [999]
    mystring += "xxx"

There are a couple of effects you need to understand in order to see
what's happening.

First, some terminology.  You don't assign values in Python, you bind a
name or another lvalue to an object.  a=650  builds an object of type
int, and binds it to the name a.  if you then say b=a, you bind b to the
*SAME* object, the previously created int object of value 650.  It can
be useful to print the id() of an object, to convince yourself that
they're actually the same. So if you print id(a) and id(b), you'll get
the same value.  But if you said  c=651 and d=651, you'd have two
objects, and the two names would be bound to different objects, with
different ids.

The += operator is an example of an augmented assignment operator. 
Others that behave the same way include *=  -=  and so on.

The += operator tries to modify the object referred to by the left hand
side, by modifying that object in place. If that fails, perhaps because
the object is immutable, then it builds a new object, and binds the left
side to that new object.

So, if you have a list, and you use += to append to it, you still have
the same list object, but it's longer now.  If you have a string, or an
int, or ... that's immutable, then it builds a new one, and binds it to
the left side.

Now, put those two operations inside a function, and what do we have ? 
Let's go through the function, looking at what happens.

Local parameter mylist gets bound to the list object bound to listb. 
The object is not copied, it's now bound to new names, one in the global
space, one local.  When the mylist +=  statement is executed, it
modifies that object, and instantly the global "variable" listb is modified.

Local parameter mystring gets bound to the string object bound to strb. 
We still only have one (immutable) object.  When the mystring +=
statement is executed, it creates a new string object by concatenating
the old one and the "xxx" string.  At this point, we can print
id(mystring) and see that it changed.  When the function returns, the
local symbols are unbound, and the new string object is discarded since
there are no longer any refs.

At this point, in top-level code, the listb object has been modified,
and the strb one has not;  it still is bound to the old value.



-- 

DaveA




More information about the Python-list mailing list