Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

semantics of [:]

0 views
Skip to first unread message

Esmail

unread,
Nov 20, 2009, 11:15:55 AM11/20/09
to pytho...@python.org
Could someone help confirm/clarify the semantics of the [:] operator
in Python?

a = range(51,55)

############# 1 ##################
b = a[:] # b receives a copy of a, but they are independent


# The following two are equivalent
############# 2 ##################
c = []
c = a[:] # c receives a copy of a, but they are independent


############# 3 ##################
d = []
d[:] = a # d receives a copy of a, but they are independent


### 1 ### is the preferred, shorter way to do what ## 2 ## and ## 3 ##
do.

Am I correct with this?

Thanks.

Diez B. Roggisch

unread,
Nov 20, 2009, 11:21:49 AM11/20/09
to
Esmail schrieb:

> Could someone help confirm/clarify the semantics of the [:] operator
> in Python?
>
> a = range(51,55)
>
> ############# 1 ##################
> b = a[:] # b receives a copy of a, but they are independent
>
>
>
> # The following two are equivalent
> ############# 2 ##################
> c = []
> c = a[:] # c receives a copy of a, but they are independent

No, the both above are equivalent. Both just bind a name (b or c) to a
list. This list is in both cases a shallow copy of a.

>
>
> ############# 3 ##################
> d = []
> d[:] = a # d receives a copy of a, but they are independent


This is a totally different beast. It modifies d in place, no rebinding
a name. So whover had a refernce to d before, now has a changed object,
whereas in the two cases above, the original lists aren't touched.

Of course, in your concrete example, the looks of it are the same. The
distinction is crucial in larger contexts.

Diez

Tim Chase

unread,
Nov 20, 2009, 12:17:54 PM11/20/09
to Diez B. Roggisch, pytho...@python.org
Diez B. Roggisch wrote:
> Esmail schrieb:
>> Could someone help confirm/clarify the semantics of the [:] operator
>> in Python?
>>
>> a = range(51,55)
>>
>> ############# 1 ##################
>> b = a[:] # b receives a copy of a, but they are independent
> >
>>
>> # The following two are equivalent
>> ############# 2 ##################
>> c = []
>> c = a[:] # c receives a copy of a, but they are independent
>
> No, the both above are equivalent. Both just bind a name (b or c) to a
> list. This list is in both cases a shallow copy of a.
>
>>
>> ############# 3 ##################
>> d = []
>> d[:] = a # d receives a copy of a, but they are independent
>
>
> This is a totally different beast. It modifies d in place, no rebinding
> a name. So whover had a refernce to d before, now has a changed object,
> whereas in the two cases above, the original lists aren't touched.

To demonstrate what Diez is saying:

a = range(51,55)
d = []
x = d
d[:] = a
print x #hey, I didn't change x...oh, yeah

-tkc

Dave Angel

unread,
Nov 20, 2009, 12:29:09 PM11/20/09
to pytho...@python.org
Diez B. Roggisch wrote:
> <div class="moz-text-flowed" style="font-family: -moz-fixed">Esmail
While Diez is correct, I think it could be less confusing. So I'll try
to put it clearer. If it's not, sorry.

(2) binds an empty list to c, and immediately rebinds it to a new list,
copied from a.. So the c=[] line is totally irrelevant, unless there's
some other code in between.

(3) again binds an empty list to d, but this is important, because the
following line wouldn't be legal if there weren't already a list. The
only time this has a different practical effect from the other two is if
there's some other code between the two lines. If that other code binds
something to the same object then it definitely matters.

I'd say (1) is the preferable form, as no visible object is in an
in-between state. The copy is built anonymously, then bound only when
it has its full value.

DaveA

Esmail

unread,
Nov 20, 2009, 1:04:39 PM11/20/09
to pytho...@python.org
Diez B. Roggisch wrote:
> Esmail schrieb:
>> Could someone help confirm/clarify the semantics of the [:] operator
>> in Python?
>>
>> a = range(51,55)
>>
>> ############# 1 ##################
>> b = a[:] # b receives a copy of a, but they are independent
> >
>>
>>
>> # The following two are equivalent
>> ############# 2 ##################
>> c = []
>> c = a[:] # c receives a copy of a, but they are independent
>
> No, the both above are equivalent. Both just bind a name (b or c) to a
> list. This list is in both cases a shallow copy of a.
>
>>
>>
>> ############# 3 ##################
>> d = []
>> d[:] = a # d receives a copy of a, but they are independent
>
>
> This is a totally different beast. It modifies d in place, no rebinding
> a name. So whover had a refernce to d before, now has a changed object,

I follow all of this up to here, the next sentence is giving me pause

> whereas in the two cases above, the original lists aren't touched.

The original list 'a', isn't changed in any of these cases right? And
modifying b, c or d would not change 'a' either - or am I not
understanding this correctly?

## 1 ##

creates a new list and copies all elements from a to b

## 2 ##

take an already existing list (empty) and copies all elements from a to
it (no data is lost by c since c was empty to start out with)

## 3 ##

d is a list, and all of its contents (if it had any) would be
filled with that of a .. but changes to a still are not reflected in d
.. this is confusing...

Semi-aside, if I wanted to make local copy of a list sent to me as a
parameter, which of these is the most appropriate to use (I don't want
changes to change the original list sent).

Thanks again.

Luis Zarrabeitia

unread,
Nov 20, 2009, 12:45:11 PM11/20/09
to pytho...@python.org
On Friday 20 November 2009 11:15:55 am Esmail wrote:
> Could someone help confirm/clarify the semantics of the [:] operator
> in Python?

In short, a[:], when "a" is a list, returns a slice ("sublist") of "a" that
happens to contain all the elemnts of "a". In general, a[low:upper:step] will
give you the sublist containing all the items from low to upper, with the
specified step size. When you omit the three arguments, you get the whole
list.

When used on the left side, it means "replace the contents of this slice with
the contents of this iterable". (The get slice and set slice behaviors are
defined by the class of «a», so while this explanation applies to list, it
may not apply, and will likely not apply, to other data structures).

Note that the sublist is always another list (even when you get the full
slice). So, in your experiments:

> ############# 1 ##################
> b = a[:] # b receives a copy of a, but they are independent

Indeed, a[:] would return a full slice, i.e, another list containing the same
elements as «a»

> # The following two are equivalent
> ############# 2 ##################
> c = []
> c = a[:] # c receives a copy of a, but they are independent

> ############# 3 ##################
> d = []
> d[:] = a # d receives a copy of a, but they are independent

Not exactly, but the difference is not big in this particular circumstance.

In (2), you create an empty list, discard it immediately, create another list
a[:] with the contents of «a», and assign it to «c».

In (3) you create an empty list, and then fill it with the elements of «a».

To see the difference, try:

e = []
g = e
e = a[:]
print g

and

e = []
g = e
e[:] = a
print g

> ### 1 ### is the preferred, shorter way to do what ## 2 ## and ## 3 ##
> do.

Depends on what you want to achieve. Some times, you need to keep the list and
change the contents. That would be (3). For instance, when updating
the "dirnames" output of the iterator returned by os.walk . Some times, you
need to discard de old list, and get a new one. (1) would be the way to go.
Note that (2) and (1) are the same, in both you discard the old value, if it
exists, but in (2) you are creating a new list only to discard it right
away - you shouldn't do that.

> Am I correct with this?

I hope I could help.

--
Luis Zarrabeitia (aka Kyrie)
Fac. de Matemática y Computación, UH.
http://profesores.matcom.uh.cu/~kyrie

Dave Angel

unread,
Nov 20, 2009, 2:08:23 PM11/20/09
to Esmail, pytho...@python.org

Esmail wrote:
> <div class="moz-text-flowed" style="font-family: -moz-fixed">Diez B.

> Roggisch wrote:
>> Esmail schrieb:
>>> Could someone help confirm/clarify the semantics of the [:] operator
>>> in Python?
>>>
>>> a = range(51,55)
>>>
>>> ############# 1 ##################
>>> b = a[:] # b receives a copy of a, but they are independent
>> >
>>>

>>> <snip>


>
>
> Semi-aside, if I wanted to make local copy of a list sent to me as a
> parameter, which of these is the most appropriate to use (I don't want
> changes to change the original list sent).
>
> Thanks again.
>
>

(1) is most appropriate in that case. In fact, unless there is other
code mixed in between, it's always the most appropriate.


DaveA

Duncan Booth

unread,
Nov 20, 2009, 3:20:49 PM11/20/09
to
Dave Angel <da...@ieee.org> wrote:

>
>
> Esmail wrote:
>> <div class="moz-text-flowed" style="font-family: -moz-fixed">Diez B.
>> Roggisch wrote:
>>> Esmail schrieb:
>>>> Could someone help confirm/clarify the semantics of the [:] operator
>>>> in Python?
>>>>
>>>> a = range(51,55)
>>>>
>>>> ############# 1 ##################
>>>> b = a[:] # b receives a copy of a, but they are independent
>>> >
>>>>
>>>> <snip>

>> <snip>


> (1) is most appropriate in that case. In fact, unless there is other
> code mixed in between, it's always the most appropriate.

An alternative view is that it is most appropriate to do:

b = list(a)

as that accepts any type of sequence for a and you don't have to remember
obscure punctuation to know what it does. The exception of course is when
(a) 'a' is sliceable and (b) you need to 'b' to be of the same type as 'a'.

Esmail

unread,
Nov 20, 2009, 4:30:26 PM11/20/09
to pytho...@python.org
Thank you all for your posts - this was very enlightening
and I printed this thread off for future reference.


Ethan Furman

unread,
Nov 20, 2009, 2:22:58 PM11/20/09
to pytho...@python.org
Dave Angel wrote:

> Esmail wrote:
>>> Esmail schrieb:
>>>
>>>> Could someone help confirm/clarify the semantics of the [:] operator
>>>> in Python?
>>>>
>>>> a = range(51,55)
>>>>
>>>> ############# 1 ##################
>>>> b = a[:] # b receives a copy of a, but they are independent
>>
>> Semi-aside, if I wanted to make local copy of a list sent to me as a
>> parameter, which of these is the most appropriate to use (I don't want
>> changes to change the original list sent).
>>
> (1) is most appropriate in that case. In fact, unless there is other
> code mixed in between, it's always the most appropriate.

Be aware: this is only a shallow copy -- if your copied list contains
mutable objects that you mutate, those changes *will* show up in the
original list.

Shallow copies are useful when, for example, you won't be mutating
objects in the copied list but are adding, removing, or reordering the
copied list.

Hope this helps.

~Ethan~

Diez B. Roggisch

unread,
Nov 20, 2009, 6:42:00 PM11/20/09
to
Esmail schrieb:

> Diez B. Roggisch wrote:
>> Esmail schrieb:
>>> Could someone help confirm/clarify the semantics of the [:] operator
>>> in Python?
>>>
>>> a = range(51,55)
>>>
>>> ############# 1 ##################
>>> b = a[:] # b receives a copy of a, but they are independent
>> >
>>>
>>>
>>> # The following two are equivalent
>>> ############# 2 ##################
>>> c = []
>>> c = a[:] # c receives a copy of a, but they are independent
>>
>> No, the both above are equivalent. Both just bind a name (b or c) to a
>> list. This list is in both cases a shallow copy of a.
>>
>>>
>>>
>>> ############# 3 ##################
>>> d = []
>>> d[:] = a # d receives a copy of a, but they are independent
>>
>>
>> This is a totally different beast. It modifies d in place, no
>> rebinding a name. So whover had a refernce to d before, now has a
>> changed object,
>
> I follow all of this up to here, the next sentence is giving me pause
>
>> whereas in the two cases above, the original lists aren't touched.
>
> The original list 'a', isn't changed in any of these cases right? And
> modifying b, c or d would not change 'a' either - or am I not
> understanding this correctly?

None of your operations changes a. But I talked about the lists you
bound b and c to before. Those aren't changed as well - they simply are
not pointed to anymore. In your example, that means the will be
garbage-collected, in other scenarios, such as this, the stay:

a = []
foo = []
bar = foo
assert bar is foo
bar = a[:]
assert bar is not foo

Diez

Esmail

unread,
Nov 20, 2009, 6:58:10 PM11/20/09
to pytho...@python.org
Diez B. Roggisch wrote:
> Esmail schrieb:
>
> None of your operations changes a. But I talked about the lists you
> bound b and c to before. Those aren't changed as well - they simply are
> not pointed to anymore. In your example, that means the will be
> garbage-collected, in other scenarios, such as this, the stay:
>
> a = []
> foo = []
> bar = foo
> assert bar is foo
> bar = a[:]
> assert bar is not foo

Got it :-) .. thanks for helping out Diez

Esmail

0 new messages