Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Python: Python

[newbie] A question about lists and strings

 

 

Python python RSS feed   Index | Next | Previous | View Threaded


mok-kong.shen at t-online

Aug 10, 2012, 2:19 AM

Post #1 of 19 (972 views)
Permalink
[newbie] A question about lists and strings

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)
--
http://mail.python.org/mailman/listinfo/python-list


vashkevichrb at gmail

Aug 10, 2012, 2:28 AM

Post #2 of 19 (966 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

10.08.2012, Χ 13:19, Mok-Kong Shen ΞΑΠΙΣΑΜ(Α):

>
> 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)
> --
> http://mail.python.org/mailman/listinfo/python-list

It seems like your xx() function doesn't return local str parameter and prints the global empty str, whereas it mutates the global list.

Roman
--
http://mail.python.org/mailman/listinfo/python-list


vashkevichrb at gmail

Aug 10, 2012, 2:48 AM

Post #3 of 19 (965 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

10.08.2012, Χ 13:28, Roman Vashkevich ΞΑΠΙΣΑΜ(Α):

> 10.08.2012, Χ 13:19, Mok-Kong Shen ΞΑΠΙΣΑΜ(Α):
>
>>
>> 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)
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>
> It seems like your xx() function doesn't return local str parameter and prints the global empty str, whereas it mutates the global list.
>
> Roman

Excuse me for the mess I just did in my message:)
The function doesn't print anything of cause. It takes list by reference and creates a new local str.
When it's called with listb and strb arguments, listb is passed by reference and mutated. A string "sss" is concatenated with an empty local str. Nothing more happens. Since local str is not returned by xx(), it can not be expected to be printed out in the statement that follows. What is printed out in the print statement is the mutated listb and the global strb.

RV
--
http://mail.python.org/mailman/listinfo/python-list


__peter__ at web

Aug 10, 2012, 2:59 AM

Post #4 of 19 (967 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

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"

a += b

is internally translated into to

a = a.__iadd__(b)

If the 'list' class were implemented in Python it would look like

class list:
def __iadd__(self, other):
for item in other:
self.append(item)
return self

i. e. the original list is modified when you perform += and you'll see the
modification when you look at any name bound to that original list:

b = a = [1, 2]
a += [3, 4]
print a # [1, 2, 3, 4]
print b # [1, 2, 3, 4]

Strings on the other hand are "immutable" -- they cannot be altered after
the initial creation. The hypothetical __iadd__() implementation is

class str:
def __iadd__(self, other):
return self + other

So += rebinds a name to a new string:

b = a = "first"
a += "second"
print b # first
print a # firstsecond

Armed with this knowledge

> lista=[]
> stra=""
> lista+=[999]

[999] is appended to lista and lista is rebound to itself.

> stra+="sss"

A new string "" + "sss" is created and stra is bound to that new string.

> print(lista,stra)


> listb=[]
> strb=""
> xx(listb,strb)

Inside xx()

(1) 999 is appended to listb and the local variable list is rebound.
(2) A new string "" + "sss" is created and bound to the local variable str.

> print(listb,strb)

If you have understood the above here's a little brain teaser:

>>> a = ([1,2,3],)
>>> a[0] += [4, 5]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

>>> a[0]

What are the contents of a[0] now?


--
http://mail.python.org/mailman/listinfo/python-list


d at davea

Aug 10, 2012, 3:07 AM

Post #5 of 19 (964 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

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

--
http://mail.python.org/mailman/listinfo/python-list


mok-kong.shen at t-online

Aug 10, 2012, 3:12 AM

Post #6 of 19 (968 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

Am 10.08.2012 11:48, schrieb Roman Vashkevich:
>[snip]
>The function .... It takes list by reference and creates a new local
> str. When it's called with listb and strb arguments, listb is passed
> by reference and mutated. A string "sss" is concatenated with an
> empty local str. Nothing more happens. Since local str is not
> returned by xx(), it can not be expected to be printed out in the
> statement that follows. What is printed out in the print statement is
> the mutated listb and the global strb.

Thanks for the explanation of the output obtained. But this means
nonetheless that parameters of types lists and strings are dealt with
in "inherently" (semantically) different ways by Python, right?

M. K. Shen

--
http://mail.python.org/mailman/listinfo/python-list


mok-kong.shen at t-online

Aug 10, 2012, 3:31 AM

Post #7 of 19 (964 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

Am 10.08.2012 12:07, schrieb Dave Angel:
[snip]
> 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.

This means there is no way of modifying a string at the top level
via a function, excepting through returning a new value and assigning
that to the string name at the top level. Please again correct me, if
I am wrong.

M. K. Shen

--
http://mail.python.org/mailman/listinfo/python-list


rosuav at gmail

Aug 10, 2012, 3:37 AM

Post #8 of 19 (965 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

On Fri, Aug 10, 2012 at 8:12 PM, Mok-Kong Shen
<mok-kong.shen [at] t-online> wrote:
> Thanks for the explanation of the output obtained. But this means
> nonetheless that parameters of types lists and strings are dealt with
> in "inherently" (semantically) different ways by Python, right?

It's nothing to do with parameters, but yes, lists are mutable and
strings are immutable. A tuple will behave the same way a string does:

>>> a
(1, 2, 3, 4)
>>> b=a
>>> a+=5, # note that "5," is a one-element tuple
>>> a
(1, 2, 3, 4, 5)
>>> b
(1, 2, 3, 4)


By the way:

On Fri, Aug 10, 2012 at 8:07 PM, Dave Angel <d [at] davea> wrote:
> 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.

To be more accurate, you *may* have two different objects. It's
possible for things to be optimized (eg with small numbers, or with
constants compiled at the same time).

ChrisA
--
http://mail.python.org/mailman/listinfo/python-list


d at davea

Aug 10, 2012, 3:37 AM

Post #9 of 19 (965 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

On 08/10/2012 06:12 AM, Mok-Kong Shen wrote:
> Am 10.08.2012 11:48, schrieb Roman Vashkevich:
>> [snip]
> >The function .... It takes list by reference and creates a new local
> > str. When it's called with listb and strb arguments, listb is passed
> > by reference and mutated. A string "sss" is concatenated with an
> > empty local str. Nothing more happens. Since local str is not
> > returned by xx(), it can not be expected to be printed out in the
> > statement that follows. What is printed out in the print statement is
> > the mutated listb and the global strb.
>
> Thanks for the explanation of the output obtained. But this means
> nonetheless that parameters of types lists and strings are dealt with
> in "inherently" (semantically) different ways by Python, right?
>
> M. K. Shen
>

Nothing to do with parameters. Lists are mutable, and strings are
immutable, so += behaves differently.



--

DaveA

--
http://mail.python.org/mailman/listinfo/python-list


rosuav at gmail

Aug 10, 2012, 3:40 AM

Post #10 of 19 (966 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

On Fri, Aug 10, 2012 at 8:31 PM, Mok-Kong Shen
<mok-kong.shen [at] t-online> wrote:
> This means there is no way of modifying a string at the top level
> via a function, excepting through returning a new value and assigning
> that to the string name at the top level. Please again correct me, if
> I am wrong.

Yes, but you can (ab)use a one-element list as a pointer.

>>> foo=["Hello"]
>>> def mutate(ptr):
ptr[0]="World"

>>> mutate(foo)
>>> print(foo[0])
World

But it's probably worth thinking about exactly why you're wanting to
change that string, and what you're really looking to accomplish.
There may well be a better way.

Chris Angelico
--
http://mail.python.org/mailman/listinfo/python-list


mok-kong.shen at t-online

Aug 10, 2012, 3:48 AM

Post #11 of 19 (967 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

Am 10.08.2012 12:40, schrieb Chris Angelico:

> But it's probably worth thinking about exactly why you're wanting to
> change that string, and what you're really looking to accomplish.
> There may well be a better way.

My problem is the following: I have at top level 3 lists and 3 strings:
lista, listb, listc and stra, strb, strc. I can with a single function
call change all 3 list values. How could I realize similar changes
of the 3 string values with a single function call?

Thanks in advance.

M. K. Shen


--
http://mail.python.org/mailman/listinfo/python-list


d at davea

Aug 10, 2012, 3:53 AM

Post #12 of 19 (963 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

On 08/10/2012 06:31 AM, Mok-Kong Shen wrote:
> Am 10.08.2012 12:07, schrieb Dave Angel:
> [snip]
>> 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.
>
> This means there is no way of modifying a string at the top level
> via a function, excepting through returning a new value and assigning
> that to the string name at the top level. Please again correct me, if
> I am wrong.
>
> M. K. Shen
>

You're close. There are three ways I can think of. The "right" way is
to return a value, which the caller can use any way he wants, including
binding it to a global.

Second is to declare the name as global, rather than taking the object
as a formal parameter. In this case, you're taking on the
responsibility for managing that particular global, by its correct name.
def yy():
global strb
strb += "whatever"

Third is to hold the string in some more complex structure which is
mutable. (untested, may contain typos)
def zz(mydict):
mydict["key1"] += "text"

called as:
globaldict = {"key1": "initial ", "key2": "init"}




--

DaveA

--
http://mail.python.org/mailman/listinfo/python-list


d at davea

Aug 10, 2012, 3:56 AM

Post #13 of 19 (965 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

On 08/10/2012 06:37 AM, Chris Angelico wrote:
> On Fri, Aug 10, 2012 at 8:12 PM, Mok-Kong Shen
> <mok-kong.shen [at] t-online> wrote:
>> Thanks for the explanation of the output obtained. But this means
>> nonetheless that parameters of types lists and strings are dealt with
>> in "inherently" (semantically) different ways by Python, right?
> It's nothing to do with parameters, but yes, lists are mutable and
> strings are immutable. A tuple will behave the same way a string does:
>
>>>> a
> (1, 2, 3, 4)
>>>> b=a
>>>> a+=5, # note that "5," is a one-element tuple
>>>> a
> (1, 2, 3, 4, 5)
>>>> b
> (1, 2, 3, 4)
>
>
> By the way:
>
> On Fri, Aug 10, 2012 at 8:07 PM, Dave Angel <d [at] davea> wrote:
>> 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.
> To be more accurate, you *may* have two different objects. It's
> possible for things to be optimized (eg with small numbers, or with
> constants compiled at the same time).
>
> ChrisA

You're right, of course. But I picked the value of 650+ deliberately,
as I believe CPython doesn't currently optimize ints over 256.



--

DaveA

--
http://mail.python.org/mailman/listinfo/python-list


vashkevichrb at gmail

Aug 10, 2012, 3:56 AM

Post #14 of 19 (967 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

10.08.2012, Χ 14:12, Mok-Kong Shen ΞΑΠΙΣΑΜ(Α):

> Am 10.08.2012 11:48, schrieb Roman Vashkevich:
>> [snip]
> >The function .... It takes list by reference and creates a new local
> > str. When it's called with listb and strb arguments, listb is passed
> > by reference and mutated. A string "sss" is concatenated with an
> > empty local str. Nothing more happens. Since local str is not
> > returned by xx(), it can not be expected to be printed out in the
> > statement that follows. What is printed out in the print statement is
> > the mutated listb and the global strb.
>
> Thanks for the explanation of the output obtained. But this means
> nonetheless that parameters of types lists and strings are dealt with
> in "inherently" (semantically) different ways by Python, right?
>
> M. K. Shen
>
> --
> http://mail.python.org/mailman/listinfo/python-list

I am not sure I understand your question. Can you rephrase it or make it more explicit?

RV
--
http://mail.python.org/mailman/listinfo/python-list


d at davea

Aug 10, 2012, 3:58 AM

Post #15 of 19 (964 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

On 08/10/2012 06:48 AM, Mok-Kong Shen wrote:
> Am 10.08.2012 12:40, schrieb Chris Angelico:
>
>> But it's probably worth thinking about exactly why you're wanting to
>> change that string, and what you're really looking to accomplish.
>> There may well be a better way.
>
> My problem is the following: I have at top level 3 lists and 3 strings:
> lista, listb, listc and stra, strb, strc. I can with a single function
> call change all 3 list values. How could I realize similar changes
> of the 3 string values with a single function call?
>
> Thanks in advance.
>
> M. K. Shen
>
>
Make sure your function returns the values, rather than just trying to
mutate them in place.

def aa(mystring1, mystring2, mystring3):
mystring1 += "something"
mystring2 += "otherthing"
mystring3 += "nobody"
return mystring1, mystring2, mystring3

str1, str2, str3 = aa(str1, str2, str3)



--

DaveA

--
http://mail.python.org/mailman/listinfo/python-list


rosuav at gmail

Aug 10, 2012, 4:00 AM

Post #16 of 19 (965 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

On Fri, Aug 10, 2012 at 8:56 PM, Dave Angel <d [at] davea> wrote:
>> On Fri, Aug 10, 2012 at 8:07 PM, Dave Angel <d [at] davea> wrote:
>>> 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.
>> To be more accurate, you *may* have two different objects. It's
>> possible for things to be optimized (eg with small numbers, or with
>> constants compiled at the same time).
>
> You're right, of course. But I picked the value of 650+ deliberately,
> as I believe CPython doesn't currently optimize ints over 256.

Yep. Also:

>>> a=651; b=651
>>> a is b
True
>>> a=651
>>> a is b
False

Same thing occurs (or at least, appears to) with constants in the same
module. Could potentially be a fairly hefty optimization, if you use
the same numbers all the time (bit flags, scale factors, modulo
divisors, etc, etc, etc).

Still doesn't alter your fundamental point of course.

ChrisA
--
http://mail.python.org/mailman/listinfo/python-list


vashkevichrb at gmail

Aug 10, 2012, 4:06 AM

Post #17 of 19 (966 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

10.08.2012, Χ 14:12, Mok-Kong Shen ΞΑΠΙΣΑΜ(Α):

> Am 10.08.2012 11:48, schrieb Roman Vashkevich:
>> [snip]
> >The function .... It takes list by reference and creates a new local
> > str. When it's called with listb and strb arguments, listb is passed
> > by reference and mutated. A string "sss" is concatenated with an
> > empty local str. Nothing more happens. Since local str is not
> > returned by xx(), it can not be expected to be printed out in the
> > statement that follows. What is printed out in the print statement is
> > the mutated listb and the global strb.
>
> Thanks for the explanation of the output obtained. But this means
> nonetheless that parameters of types lists and strings are dealt with
> in "inherently" (semantically) different ways by Python, right?
>
> M. K. Shen
>
> --
> http://mail.python.org/mailman/listinfo/python-list

DaveA provided a very explicit explanation of how py handles list and string objects.
Parameters are handled "inherently" by functions...

RV
--
http://mail.python.org/mailman/listinfo/python-list


mok-kong.shen at t-online

Aug 10, 2012, 4:08 AM

Post #18 of 19 (965 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

Am 10.08.2012 12:56, schrieb Roman Vashkevich:

> I am not sure I understand your question. Can you rephrase it or make it more explicit?

I have just detailed my problem and Dave Angel has shown how to solve
it properly.

M. K. Shen

--
http://mail.python.org/mailman/listinfo/python-list


sg552 at hotmail

Aug 10, 2012, 8:12 AM

Post #19 of 19 (951 views)
Permalink
Re: [newbie] A question about lists and strings [In reply to]

On 10/08/2012 10:59, Peter Otten wrote:
> [...]
>
> If you have understood the above here's a little brain teaser:
>
>>>> a = ([1,2,3],)
>>>> a[0] += [4, 5]
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: 'tuple' object does not support item assignment
>
>>>> a[0]
>
> What are the contents of a[0] now?

Ha, nice.


--
I have made a thing that superficially resembles music:

http://soundcloud.com/eroneity/we-berated-our-own-crapiness
--
http://mail.python.org/mailman/listinfo/python-list

Python python RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.