简体   繁体   中英

Integer and referencing on python list slicing

Could anybody explain the following list reference issue? I haven't understood it clearly .

For example :

>>> a = [1,2,3,4]
>>> a[0:2] = 11,22
>>> a
[11, 22, 3, 4]
>>> b = a[0:2]
>>> b[0:2] = 33,44
>>> b
[33, 44]
>>> a
[11, 22, 3, 4]

Why does a[0:2] = 11,22 changes the list a but b[0:2] = 33,44 doesn't? Isn't b referencing a[0:2] ? Why list's reference is changing its value, but integer's reference it won't?

Example:

>>> a = 1
>>> b = a
>>> a = 2
>>> b
1

I think it is self-explanatory.

>>> a = [1,2,3,4]  
>>> a[0:2] = 11,22  
>>> a  
[11, 22, 3, 4]    

You are modifying the value at the indices 0 and 1 of a. So, original values at indices 2 and 3 remain unchanged.

>>> b = a[0:2]  
>>> b[0:2] = 33,44  
>>> b  
[33, 44]  
>>> a  
[11, 22, 3, 4]  

You have copied the values at indices 0 and 1 from a to b and hence b has only 2 values. Then you are overwriting the values of b with [33,44] . Hence the results what you observe.

There are certain data types which are immutable (values cannot be changed) such as numbers, strings, tuple. Data types like dict, list are mutable (values can be changed)

Illustration

>>> a = [1,2,3,4]
>>> b = a
>>> id(a)
46734952
>>> id(b)
46734952  

>>> b[1] = 8
>>> print(b)
[1, 8, 3, 4]
>>> print(a)
[1, 8, 3, 4]  

In the above case, b is a reference to a . ie, Both a and b is pointing to the same list. Any change made to b will affect a also. This can be verified by using the id function. Same id value says that both point to the same object.

>>> c = a[:]
>>> print(c)
[1, 8, 3, 4]
>>> id(a)
46734952
>>> id(c)
46563240  

In the above case, slice of a is assigned to c . Hence a copy is made and assigned to c . Hence the id value of a and c are different.

Because there are two types of data

  1. mutable data types

    • list
    • dict
    • set
    • classes
  2. immutable data types

    • numbers (boolean, integer, float and complex numbers)
    • string
    • tuple
    • frozenset

When you change mutable type you change it object and when you change immutable type you create new object and then assign it to variable

I'll answer step by step:

a[0:2] = 11,22

Is the same as doing a[0] = 11; a[1] = 22 a[0] = 11; a[1] = 22 . That's regular assignment, no surprises here. When you do:

b = a[0:2]

You get a shallow copy of the list. This means that you get a new list, with a reference to each object. Since in your case the list is filled with int s, it's essentially a copy as well. But consider this example:

Let's define a class, which wraps an int (or any other data type, it's python :) ), but is mutable.

In [41]: class num(object):
    ...:     def __init__(self, x):
    ...:         self.x = x
    ...:         

Now we'll define a as before, only with our class

In [42]: a = [num(x) for x in range(1,5)]

In [43]: a[0].x
Out[43]: 1

In [44]: a[1].x
Out[44]: 2

Now, we'll assign a slice of a into b . Contrary to your example, when the list held the values of the numbers, here it hold the reference, so you could say they are the same:

In [45]: b = a[0:2]

In [46]: b[0].x
Out[46]: 1

In [47]: b[1].x
Out[47]: 2

So when I change one in b :

In [48]: b[0].x = 3

It's reflected in a :

In [50]: a[0].x
Out[50]: 3

But it's a different list. So assigning a new instance to a place in the list...

In [49]: b[1] = num(20)

... is not reflected in a :

In [51]: a[1].x
Out[51]: 2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM