Python references and object comprehension

Reprinted by: Shaun Chen

When I was browsing the blog today, I saw this sentence: Variable names and objects in python are separated ;

At first, I didn't react when I saw this sentence. Decided to figure out the details between variables and objects in python. (Actually, I feel that it is more appropriate to say that references and objects are separated)

Start thinking with the first variable:

In python, if you want to use a variable, you don't need to declare it in advance, you only need to assign a value to the variable when you use it (this is different from statically typed languages ​​such as C language, and python is dynamically typed).

First example:

a = 1

This is a simple assignment statement. The integer 1 is an object, and a is a reference. Using the assignment statement, the reference a points to the object 1; The "line" in the hand, python is just like that "line", by reference to touch and tie the kite in the sky - the object.

You can view the identity of an object through python's built-in function id(), which is actually the memory address of the object :

Note: Python's concept of everything is an object, so a function is also an object, so you can use the __doc__ method of the id() function to view the specific description of this function :

>>> id.__doc__
    "id(object) -> integer\n\nReturn the identity of an object. This is guaranteed to be unique among\nsimultaneously existing objects.       (Hint: it's the object's memory address.)"

Second example:

a = 2

a = 'banana'

Use the id() function used in the first chestnut above: 

>>> a = 1
>>> id(a) 
24834392
>>> a = 'banana'
>>> id(a)
139990659655312

In the first statement, 2 is an integer object stored in memory, which points to object 1 by assigning a reference to a

In the second statement, a string object 'banana' is created in the memory, and the reference a points to 'banana' through assignment. Object 1 no longer has a reference to it, and it will be garbage collected by python's memory processing mechanism. ,

Free up memory.

Third example:

a = 3

b = 3

View the reference of variable a and variable b through the function: 

>>> a = 3
>>> b = 3
>>> id(a)
10289448
>>> id(b)
10289448

Here you can see that these two references point to the same object, why is this? This is related to python's memory mechanism, because for the language, frequent object destruction and creation is a waste of performance. So in Python, integers and short characters, Python caches these objects for reuse.

Fourth example:

1.  a = 4

2. b = a (here is to let reference b point to the object pointed to by reference a)

3.  a = a + 2

View references by function:

When you get to step 2, look at the references to a and b: 

>>> a = 4
>>> b = a
>>> id(a)
36151568
>>> id(b)
36151568

You can see that both a and b point to integer objects 4

Next point to step 3:

>>> a = a+2
>>> id(a)
36151520
>>> id(b)
36151568

It can be seen that the reference of a has changed, but the reference of b has not changed; a and b point to different objects; the third sentence reassigns a to point to a new object 6; even if multiple references point to different objects the same object,

If a reference value changes, it actually makes this reference point to a new reference, and does not affect the pointing of other references. From the effect point of view, each reference is independent of each other and does not affect each other.

Fifth example (this example will involve mutable and immutable data types in python):

Before starting this example, remember to note the difference in the fourth example.

1.   L1 = [1, 2, 3]

2. L2 = L1

3.   L1[0] = 10

View references by function:

当执行第1步 和 第二步 的时候,查看一下 L1 和 L2 的引用情况:

>>> L1 = [1,2,3]
>>> L2 = L1
>>> id(L1)
139643051219496
>>> id(L2)
139643051219496

此时 L1 和 L2 的引用相同,都是指向 [1,2,3]这个列表对象。

接下来,继续执行第3步:

>>> L1[0] = 10
>>> id(L1)
139643051219496
>>> id(L2)
139643051219496
>>> L2
[10, 2, 3]

同样的跟第四个例子那样,修改了其中一个对象的值,但是可以发现 结果并不与第四个例子那样, 在本次实验中,L1 和 L2 的引用没有发生任何变化,但是列表对象[1,2,3] 的值 变成了 [10,2,3](列表对象改变了)

在该情况下,我们不再对L1这一引用赋值,而是对L1所指向的表的元素赋值。结果是,L2也同时发生变化。

原因何在呢?因为L1,L2的指向没有发生变化,依然指向那个表。表实际上是包含了多个引用的对象(每个引用是一个元素,比如L1[0],L1[1]..., 每个引用指向一个对象,比如1,2,3), 。而L1[0] = 10这一赋值操作,并不是改变L1的指向,而是对L1[0], 也就是表对象的一部份(一个元素),进行操作,所以所有指向该对象的引用都受到影响。(与之形成对比的是,我们之前的赋值操作都没有对对象自身发生作用,只是改变引用指向。)

看一个例子:

L1 = [1, 2, 3]
L2 = L1
print(id(L1))
print(id(L2))
print(id(L1[0]), id(L1[1]), id(L1[2]))

L1[0] = 10
print(L1, L2)
print(id(L1[0]), id(L1[1]), id(L1[2]))

输出结果:

2276118458184
2276118458184
1424059872 1424059904 1424059936
[10, 2, 3] [10, 2, 3]
1424060160 1424059904 1424059936

发现改变的仅仅是id(L1[0]),与以上结论相符。

列表可以通过引用其元素,改变对象自身(in-place change)。这种对象类型,称为可变数据对象(mutable object),词典也是这样的数据类型。

而像之前的数字和字符串,不能改变对象本身,只能改变引用的指向,称为不可变数据对象(immutable object)。

我们之前学的元组(tuple),尽管可以调用引用元素,但不可以赋值,因此不能改变对象自身,所以也算是immutable object.

is关键字:

当然,我们也可以要想知道是否指向同一个对象,我们可以使用 python的 is 关键词,is用于判断两个引用所指的对象是否相同。

就像上述第四个例子 当进行到第1步和第2步的时候:

>>> a = 4   ……id(a) = 36151568
>>> b = a   ……id(b) = 36151568
>>> a is b  
True

当进行到第3步的时候:

>>> a = a + 2  ……id(a) = 36151520
>>> a is b     ……id(b) = 36151568
False

突然想到,对于python 的 深拷贝 和 浅拷贝 的理解,也是可以根据这个进行验证,可以通过第五个例子进行辅助理解。

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324976911&siteId=291194637