当前位置:天才代写 > tutorial > Python教程 > Python 中的引用和类属性的领略

Python 中的引用和类属性的领略

2017-11-02 08:00 星期四 所属: Python教程 浏览:1062

最近对Python 的工具引用机制稍微研究了一下,留下条记,以供查阅。

首先有一点是明晰的:「Python 中一切皆工具」。

那么,这到底意味着什么呢?

如下代码:

#!/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

运行功效如下: 

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

从「Origin」部门来看,list 中各个元素的地点之间都正好相差24,依次指向各自的数据——这让我想到了数组。

当修改a[0] 的值之后,发明,a[0] 的地点产生了变革。也就是说,赋值语句实际上只是让a[0] 从头指向另一个工具罢了。另外,还留意到,a[0] 的地点和a[2]的地点相差48(2个24)。

当再次修改a[1] 之后,同样地,a[1] 的地点也产生变革,有趣的是,这次a[1] 的地点和a[0] 的地点又相差24,和原先的a[2] 相差72(3个24)。

最后,当直接把数字0的地点打印出来后,发明它的地点和最开始的a[0] 的地点完全一样。

至此,根基可以说明,就算是list 中的元素,其实也是引用。修改list 中的元素,实际上照旧在修改引用罢了。

对付Python 中类属性,有人提到过「类属性在同一类及其子类之间共享,修改类属性会影响到同一类及其子类的所有工具」。

听着挺吓人,但仔细研究之后,其实倒也不是什么大不了的工作。

如下代码:

#!/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 '----------------------------'

#p#分页标题#e#

运行功效:

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']
----------------------------

在「Origin」的时候,同类工具,子类工具的沟通类属性的地点都是沟通的——这就是所谓的「共享」。

修改name 之后,只有被修改的工具name 属性产生变革。这是因为对name的赋值操纵实际上就是换了一个字符串,从头引用。字符串自己并没有产生变革。所以并没有在同类和子类之间发生相互影响。

接下来,修改talent 中的元素。这时,环境有所改变:同类及其子类的talent 属性都一起随着变了——这很好领略,因为它们都引用的内存地点都一样,引用的是同一个工具。

再接下来,给talent 从头赋值,也就是改成引用别的一个工具。功效是只有本实例的talent 属性变革了。从内存地点可以看出,本实例和其他实例的talent 属性已经不再指向沟通的工具了。就是说「至此,本实例已经是第三者士了」。

那么,最后再次修改talent 中元素后,对其他实例无影响的功效也是很好领略了。因为已经是「第三者士」了嘛,我再怎么折腾也都是本身的工作了。

所以,「类属性在同类及其子类之间相互影响」必需有一个前提条件:实例成立后,其类属性从来没有被从头赋值过,即类属性依然指向最初所指向的内存地点。

最后提一下工具属性

如下代码:

#!/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']
--------------------

#p#分页标题#e#

由于工具属性就算内容完全一样(刚初始化后的属性内容一般都是一样的),也会分派到完全差异的内存地点上去。所以不存在「同类工具之间影响」的环境。

但假如让一个工具的属性和另一个工具的属性指向同一个地点,两者之间(但也仅限两者之间)便又相互连累起来。

 

    关键字:

天才代写-代写联系方式