[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

a trick with lists ?

Sébastien Vincent" <sebastien_nimp73

2/7/2008 5:21:00 PM

I've found some class on the Net which takes basically this form :

######
class Foo:
def __init__(self):
self.tasks = []
...

def method1(self):
tasks = []
while True:
...
append/pop elements into/from tasks
...
if condition : break

self.tasks[:] = tasks
return
######

What I do not fully understand is the line "self.tasks[:] = tasks". Why does
the guy who coded this did not write it as "self.tasks = tasks"? What is the
use of the "[:]" trick ?




10 Answers

Diez B. Roggisch

2/7/2008 5:32:00 PM

0

"S����������������������������������������������" schrieb:
> I've found some class on the Net which takes basically this form :
>
> ######
> class Foo:
> def __init__(self):
> self.tasks = []
> ...
>
> def method1(self):
> tasks = []
> while True:
> ...
> append/pop elements into/from tasks
> ...
> if condition : break
>
> self.tasks[:] = tasks
> return
> ######
>
> What I do not fully understand is the line "self.tasks[:] = tasks". Why does
> the guy who coded this did not write it as "self.tasks = tasks"? What is the
> use of the "[:]" trick ?

It changes the list in-place. If it has been given to other objects, it
might require that.


Diez

Steve Holden

2/7/2008 9:16:00 PM

0

Diez B. Roggisch wrote:
> "S����������������������������������������������" schrieb:
>> I've found some class on the Net which takes basically this form :
>>
>> ######
>> class Foo:
>> def __init__(self):
>> self.tasks = []
>> ...
>>
>> def method1(self):
>> tasks = []
>> while True:
>> ...
>> append/pop elements into/from tasks
>> ...
>> if condition : break
>>
>> self.tasks[:] = tasks
>> return
>> ######
>>
>> What I do not fully understand is the line "self.tasks[:] = tasks". Why does
>> the guy who coded this did not write it as "self.tasks = tasks"? What is the
>> use of the "[:]" trick ?
>
> It changes the list in-place. If it has been given to other objects, it
> might require that.

Nowadays it's stylistically better to write

self.tasks = list(tasks)

as it does just the same and makes it a little clearer what's going on
(though of course if tasks *isn't* a list it won't do *exactly* the same.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.hold...

James Turk

2/7/2008 9:19:00 PM

0

On Feb 7, 12:20 pm, "Sébastien Vincent" <sebastien_nimp73<@>free.fr>
wrote:
> I've found some class on the Net which takes basically this form :
>
> ######
> class Foo:
> def __init__(self):
> self.tasks = []
> ...
>
> def method1(self):
> tasks = []
> while True:
> ...
> append/pop elements into/from tasks
> ...
> if condition : break
>
> self.tasks[:] = tasks
> return
> ######
>
> What I do not fully understand is the line "self.tasks[:] = tasks". Why does
> the guy who coded this did not write it as "self.tasks = tasks"? What is the
> use of the "[:]" trick ?

if you do
a = [1,2,3]
b = []
b = a

then assign: b[1] = 9
now a[1] == 9 as well

with a[:] = b you are actually getting a copy of the list rather than
an alias

it's hard to say if this is needed in the case you described without
context, but that's what the a[:] = b idiom does

-James

imho

2/7/2008 9:29:00 PM

0

Steve Holden ha scritto:

>>> What I do not fully understand is the line "self.tasks[:] = tasks".
>>> Why does the guy who coded this did not write it as "self.tasks =
>>> tasks"? What is the use of the "[:]" trick ?
>>
>> It changes the list in-place. If it has been given to other objects,
>> it might require that.
>
> Nowadays it's stylistically better to write
>
> self.tasks = list(tasks)
>
> as it does just the same and makes it a little clearer what's going on
> (though of course if tasks *isn't* a list it won't do *exactly* the same.
>
> regards
> Steve

No:

self.tasks = list(tasks) is the same of self.tasks = tasks[:], not a
replacement for self.tasks[:] = tasks , the latter performing a
different operation, i.e. resetting the list self.tasks 'in place'
without assigning it a different list.

Ed Leafe

2/7/2008 9:34:00 PM

0

On Feb 7, 2008, at 3:19 PM, James Turk wrote:

> if you do
> a = [1,2,3]
> b = []
> b = a
>
> then assign: b[1] = 9
> now a[1] == 9 as well
>
> with a[:] = b you are actually getting a copy of the list rather than
> an alias


Of course, this only works if 'b' is already a list. A more common
and more general usage for making list copies would be:

a = [1,2,3]
b = a[:]

In this usage, 'a' and 'b' are separate lists, but 'b' doesn't need
to be defined as a list first.

-- Ed Leafe



bruno.desthuilliers@gmail.com

2/7/2008 9:38:00 PM

0

On 7 fév, 22:16, Steve Holden <st...@holdenweb.com> wrote:
> Diez B. Roggisch wrote:
> >> self.tasks[:] = tasks
>
> >> What I do not fully understand is the line "self.tasks[:] = tasks". Why does
> >> the guy who coded this did not write it as "self.tasks = tasks"? What is the
> >> use of the "[:]" trick ?
>
> > It changes the list in-place. If it has been given to other objects, it
> > might require that.
>
> Nowadays it's stylistically better to write
>
> self.tasks = list(tasks)
>
> as it does just the same

Err... not quite, actually.

>>> class Foo(object):
... def __init__(self):
... self.tasks = range(5)
... def test1(self):
... self.tasks[:] = ['a', 'b', 'c']
... def test2(self):
... self.tasks = list(['d', 'e', 'f'])
...
>>> f = Foo()
>>> f.tasks
[0, 1, 2, 3, 4]
>>> alias = f.tasks
>>> alias is f.tasks
True
>>> f.test1()
>>> f.tasks
['a', 'b', 'c']
>>> alias
['a', 'b', 'c']
>>> alias is f.tasks
True
>>> f.test2()
>>> f.tasks
['d', 'e', 'f']
>>> alias
['a', 'b', 'c']
>>> alias is f.tasks
False
>>>



> and makes it a little clearer what's going on
> (though of course if tasks *isn't* a list it won't do *exactly* the same.
>
> regards
> Steve
> --
> Steve Holden +1 571 484 6266 +1 800 494 3119
> Holden Web LLC http://www.hold...

Tim Chase

2/7/2008 9:43:00 PM

0

>>> self.tasks[:] = tasks
>>>
>>> What I do not fully understand is the line "self.tasks[:] = tasks". Why does
>>> the guy who coded this did not write it as "self.tasks = tasks"? What is the
>>> use of the "[:]" trick ?
>>
>> It changes the list in-place. If it has been given to other objects, it
>> might require that.
>
> Nowadays it's stylistically better to write
>
> self.tasks = list(tasks)
>
> as it does just the same and makes it a little clearer what's going on

Um...except it's not "just the same"?

class Foo(object):
def __init__(self, tasks):
self.tasks1 = tasks
self.todo1 = [self.tasks1, 42]
self.tasks2 = tasks
self.todo2 = [self.tasks2, 42]
def new_tasks1(self, tasks):
self.tasks1 = list(tasks)
def new_tasks2(self, tasks):
self.tasks2[:] = list(tasks)
def __str__(self):
return "%r\n%r" % (self.todo1, self.todo2)

f = Foo([1,2,3])

f.new_tasks1([4,5,6])
print 'task1'
print f # todo1/2 haven't been changed

print 'task2'
f.new_tasks2([4,5,6])
print f # both todo 1 & 2 have been changed

Assignment to a name just rebinds that name. Assignment to a
slice of a list replaces the contents in-place.

-tkc



Steve Holden

2/7/2008 10:53:00 PM

0

Tim Chase wrote:
>>>> self.tasks[:] = tasks
>>>>
>>>> What I do not fully understand is the line "self.tasks[:] = tasks". Why does
>>>> the guy who coded this did not write it as "self.tasks = tasks"? What is the
>>>> use of the "[:]" trick ?
>>> It changes the list in-place. If it has been given to other objects, it
>>> might require that.
>> Nowadays it's stylistically better to write
>>
>> self.tasks = list(tasks)
>>
>> as it does just the same and makes it a little clearer what's going on
>
> Um...except it's not "just the same"?
>
> class Foo(object):
> def __init__(self, tasks):
> self.tasks1 = tasks
> self.todo1 = [self.tasks1, 42]
> self.tasks2 = tasks
> self.todo2 = [self.tasks2, 42]
> def new_tasks1(self, tasks):
> self.tasks1 = list(tasks)
> def new_tasks2(self, tasks):
> self.tasks2[:] = list(tasks)
> def __str__(self):
> return "%r\n%r" % (self.todo1, self.todo2)
>
> f = Foo([1,2,3])
>
> f.new_tasks1([4,5,6])
> print 'task1'
> print f # todo1/2 haven't been changed
>
> print 'task2'
> f.new_tasks2([4,5,6])
> print f # both todo 1 & 2 have been changed
>
> Assignment to a name just rebinds that name. Assignment to a
> slice of a list replaces the contents in-place.
>
[sigh] Right, I got the assignment the wrong way around (and clearly you
can't put list(tasks) on the left-hand side of an assignment).

Of course

self.tasks = list(tasks)

is equivalent to

self.tasks = tasks[:]

Thanks for pointing out my error.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.hold...

Helmut Jarausch

2/8/2008 9:40:00 AM

0

Sébastien Vincent <sebastien_nimp73 wrote:
> I've found some class on the Net which takes basically this form :
>
> ######
> class Foo:
> def __init__(self):
> self.tasks = []
> ...
>
> def method1(self):
> tasks = []
> while True:
> ...
> append/pop elements into/from tasks
> ...
> if condition : break
>
> self.tasks[:] = tasks
> return
> ######
>
> What I do not fully understand is the line "self.tasks[:] = tasks". Why does
> the guy who coded this did not write it as "self.tasks = tasks"? What is the
> use of the "[:]" trick ?
>

I've just run into this difference myself.
As several others have pointed out, assignment to
self.task[:] modifies this list in place.

Here my example showing a striking difference

class MyClass(object) :
def shorten_list(self,outer_list) :
ll=len(outer_list)
if ll > 0 :
outer_list[:]= outer_list[:ll-1]


mylist=[1,2,3]
MyClass().shorten_list(mylist)
print mylist

// this prints [1, 2] (as expected)

class MyClass2(object) :
def shorten_list(self,outer_list) :
ll=len(outer_list)
if ll > 0 :
outer_list= outer_list[:ll-1]


mylist=[1,2,3]
MyClass2().shorten_list(mylist)
print mylist

# this prints [1, 2, 3]

The shortened list outer_list[:ll-1] has been assigned (bound in Python terms)
to the LOCAL reference (to a list) 'outer_list'

--
Helmut Jarausch

Lehrstuhl fuer Numerische Mathematik
RWTH - Aachen University
D 52056 Aachen, Germany

Sébastien Vincent" <sebastien_nimp73

2/8/2008 10:35:00 AM

0

Thank you, that's very clear indeed.

"Helmut Jarausch" <jarausch@igpm.rwth-aachen.de> a écrit dans le message de
news: 612mcfF1sa420U1@mid.dfncis.de...
> Sébastien Vincent <sebastien_nimp73 wrote:
>> I've found some class on the Net which takes basically this form :
>>
>> ######
>> class Foo:
>> def __init__(self):
>> self.tasks = []
>> ...
>>
>> def method1(self):
>> tasks = []
>> while True:
>> ...
>> append/pop elements into/from tasks
>> ...
>> if condition : break
>>
>> self.tasks[:] = tasks
>> return
>> ######
>>
>> What I do not fully understand is the line "self.tasks[:] = tasks". Why
>> does the guy who coded this did not write it as "self.tasks = tasks"?
>> What is the use of the "[:]" trick ?
>>
>
> I've just run into this difference myself.
> As several others have pointed out, assignment to
> self.task[:] modifies this list in place.
>
> Here my example showing a striking difference
>
> class MyClass(object) :
> def shorten_list(self,outer_list) :
> ll=len(outer_list)
> if ll > 0 :
> outer_list[:]= outer_list[:ll-1]
>
>
> mylist=[1,2,3]
> MyClass().shorten_list(mylist)
> print mylist
>
> // this prints [1, 2] (as expected)
>
> class MyClass2(object) :
> def shorten_list(self,outer_list) :
> ll=len(outer_list)
> if ll > 0 :
> outer_list= outer_list[:ll-1]
>
>
> mylist=[1,2,3]
> MyClass2().shorten_list(mylist)
> print mylist
>
> # this prints [1, 2, 3]
>
> The shortened list outer_list[:ll-1] has been assigned (bound in Python
> terms)
> to the LOCAL reference (to a list) 'outer_list'
>
> --
> Helmut Jarausch
>
> Lehrstuhl fuer Numerische Mathematik
> RWTH - Aachen University
> D 52056 Aachen, Germany