Recently, I have done a little research on Python’s object reference mechanism and left notes for reference.
First of all, one thing is clear: "Everything in Python is an object."
So, what does this mean?
The following code:
#!/usr/bin/env python a = [0, 1, 2] # 来个简单的list # 最初,list 和其中各个元素的id 是这样的。 print 'origin' print id(a),a for x in a: print id(x), x print '----------------------' # 我们把第一个元素改改 print 'after change a[0]' a[0] = 4 print id(a),a for x in a: print id(x), x print '----------------------' # 我们再把第二个元素改改 print 'after change a[1]' a[1] = 5 print id(a),a for x in a: print id(x), x print '----------------------' # 回头看看直接写个0 ,id是多少 print 'how about const 0?' print id(0), 0
The running results are as follows:
PastgiftMacbookPro:python pastgift$ ./refTest.py Origin 4299760200 [0, 1, 2] 4298181328 0 4298181304 1 4298181280 2 ---------------------- after change a[0] 4299760200 [4, 1, 2] 4298181232 4 4298181304 1 4298181280 2 ---------------------- after change a[1] 4299760200 [4, 5, 2] 4298181232 4 4298181208 5 4298181280 2 ---------------------- how about const 0? 4298181328 0
From the "Origin" part, the addresses of each element in the list are exactly 24 different from each other, pointing to their respective data in turn - — which brings me to arrays.
After modifying the value of a[0], it was found that the address of a[0] has changed. In other words, the assignment statement actually just makes a[0] point to another object again. In addition, it is also noted that the address of a[0] and the address of a[2] differ by 48 (two 24s).
When a[1] is modified again, the address of a[1] also changes. Interestingly, this time the address of a[1] and the address of a[0] differ by 24, which is different from the original a[2] differs by 72 (three 24s).
Finally, after printing the address of the number 0 directly, we found that its address is exactly the same as the address of the original a[0].
At this point, it can be basically explained that even the elements in the list are actually references. Modifying the elements in the list is actually modifying the reference.
Regarding class attributes in Python, someone mentioned that "class attributes are shared between the same class and its subclasses, and modifying class attributes will affect all objects of the same class and its subclasses."
It sounds scary, but after careful study, it’s actually not a big deal.
The following code:
#!/usr/bin/env python class Bird(object): name = 'bird' talent = ['fly'] class Chicken(Bird): pass bird = Bird(); bird2 = Bird(); # 同类实例 chicken = Chicken(); # 子类实例 # 最开始是这样的 print 'Original attr' print id(bird.name), bird.name print id(bird.talent), bird.talent print id(bird2.name), bird2.name print id(bird2.talent), bird2.talent print id(chicken.name), chicken.name print id(chicken.talent), chicken.talent print '----------------------------' # 换个名字看看 bird.name = 'bird name changed!' print 'after changing name' print id(bird.name), bird.name print id(bird.talent), bird.talent print id(bird2.name), bird2.name print id(bird2.talent), bird2.talent print id(chicken.name), chicken.name print id(chicken.talent), chicken.talent print '----------------------------' # 洗个天赋试试(修改类属性中的元素) bird.talent[0] = 'walk' print 'after changing talent(a list)' print id(bird.name), bird.name print id(bird.talent), bird.talent print id(bird2.name), bird2.name print id(bird2.talent), bird2.talent print id(chicken.name), chicken.name print id(chicken.talent), chicken.talent print '----------------------------' # 换个新天赋树(整个类属性全换掉) bird.talent = ['swim'] print 'after reassign talent' print id(bird.name), bird.name print id(bird.talent), bird.talent print id(bird2.name), bird2.name print id(bird2.talent), bird2.talent print id(chicken.name), chicken.name print id(chicken.talent), chicken.talent print '----------------------------' # 洗掉新天赋树(对新来的类属性中的元素进行修改) bird.talent[0] = 'dance' print 'changing element after reassigning talent' print id(bird.name), bird.name print id(bird.talent), bird.talent print id(bird2.name), bird2.name print id(bird2.talent), bird2.talent print id(chicken.name), chicken.name print id(chicken.talent), chicken.talent print '----------------------------'
Running result:
PastgiftMacbookPro:python pastgift$ ./changeAttributeTest.py Original attr 4301998000 bird 4301857352 ['fly'] 4301998000 bird 4301857352 ['fly'] 4301998000 bird 4301857352 ['fly'] ---------------------------- after changing name 4301986984 bird name changed! 4301857352 ['fly'] 4301998000 bird 4301857352 ['fly'] 4301998000 bird 4301857352 ['fly'] ---------------------------- after changing talent(a list) 4301986984 bird name changed! 4301857352 ['walk'] 4301998000 bird 4301857352 ['walk'] 4301998000 bird 4301857352 ['walk'] ---------------------------- after reassign talent 4301986984 bird name changed! 4301859512 ['swim'] 4301998000 bird 4301857352 ['walk'] 4301998000 bird 4301857352 ['walk'] ---------------------------- changing element after reassigning talent 4301986984 bird name changed! 4301859512 ['dance'] 4301998000 bird 4301857352 ['walk'] 4301998000 bird 4301857352 ['walk'] ----------------------------
In "Origin", the addresses of the same class attributes of similar objects and subclass objects are the same - this is what is called "sharing".
After modifying the name, only the name attribute of the modified object changes. This is because the assignment operation to name is actually changing a string and re-quoting it. The string itself has not changed. Therefore, there is no mutual influence between the same category and subcategories.
Next, modify the elements in talent. At this time, the situation has changed: the talent attributes of the same class and its subclasses have all changed together - this is easy to understand, because they all refer to the same memory address and refer to the same object.
Next, reassign the talent, that is, change it to reference another object. The result is that only the talent attribute of this instance changes. It can be seen from the memory address that the talent attributes of this instance and other instances no longer point to the same object. That is to say, "At this point, this example is already an outsider."
Then, after finally modifying the elements in talent again, it is easy to understand that it has no effect on other instances. Because I am already an "outsider", no matter how much I mess with it, it is all my own business.
So, "class attributes affect each other between the same class and its subclasses" must have a prerequisite: after the instance is created, its class attributes have never been reassigned, that is, the class attributes still point to the memory address originally pointed to.
Finally, let’s mention the object attributes
The following code:
#!/usr/bin/env python class Bird(object): def __init__(self): self.talent = ['fly'] bird = Bird() bird2 = Bird() # 刚开始的情形 print 'Origin' print id(bird.talent), bird.talent print id(bird2.talent), bird2.talent print '--------------------' # 修改其中一个对象的属性 bird.talent[0] = 'walk' print 'after changing attribute' print id(bird.talent), bird.talent print id(bird2.talent), bird2.talent print '--------------------' # 作死:两个对象的属性指向同一个内存地址,再修改 bird.talent = bird2.talent bird.talent[0] = 'swim' print 'assign to another attribute and change it' print id(bird.talent), bird.talent print id(bird2.talent), bird2.talent print '--------------------' 运行结果: PastgiftMacbookPro:python pastgift$ ./changeAttributeTest2.py Origin 4299867632 ['fly'] 4299760200 ['fly'] -------------------- after changing attribute 4299867632 ['walk'] 4299760200 ['fly'] -------------------- assign to another attribute and change it 4299760200 ['swim'] 4299760200 ['swim'] --------------------
Since the object attributes have exactly the same content (the attribute content after initialization is generally the same), they will be allocated to completely different memory addresses. . Therefore, there is no "influence between similar objects".
But if the attributes of one object and the attributes of another object point to the same address, the two (but only between the two) will be involved in each other.