semantics of [:]

E

Esmail

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.
 
D

Diez B. Roggisch

Esmail said:
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
 
T

Tim Chase

Diez said:
Esmail said:
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
 
D

Dave Angel

Diez said:
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
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
 
E

Esmail

Diez said:
Esmail said:
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.
 
D

Dave Angel

Esmail said:
Esmail said:
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
 
E

Ethan Furman

Dave said:
Esmail said:
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~
 
D

Diez B. Roggisch

Esmail said:
Diez said:
Esmail said:
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
 
E

Esmail

Diez said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,241
Latest member
Lisa1997

Latest Threads

Top