国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

從零學Python之引用和類屬性的初步理解

2019-11-25 18:25:05
字體:
來源:轉載
供稿:網友

Python是一種解釋型、面向對象、動態數據類型的高級程序設計語言。自從20世紀90年代初Python語言誕生至今,它逐漸被廣泛應用于處理系統管理任務和Web編程。Python已經成為最受歡迎的程序設計語言之一。2011年1月,它被TIOBE編程語言排行榜評為2010年度語言。自從2004年以后,python的使用率是呈線性增長。

Python在設計上堅持了清晰劃一的風格,這使得Python成為一門易讀、易維護,并且被大量用戶所歡迎的、用途廣泛的語言。

鑒于以上各種優點,忍不住對Python進行了一番學習,略有收獲,分享給大家。

最近對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
[0, 1, 2]
0
1
2
----------------------
after change a[0]
[4, 1, 2]
4
1
2
----------------------
after change a[1]
[4, 5, 2]
4
5
2
----------------------
how about const 0?
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 '----------------------------'

運行結果:

復制代碼 代碼如下:

PastgiftMacbookPro:python pastgift$ ./changeAttributeTest.py
Original attr
bird
['fly']
bird
['fly']
bird
['fly']
----------------------------
after changing name
bird name changed!
['fly']
bird
['fly']
bird
['fly']
----------------------------
after changing talent(a list)
bird name changed!
['walk']
bird
['walk']
bird
['walk']
----------------------------
after reassign talent
bird name changed!
['swim']
bird
['walk']
bird
['walk']
----------------------------
changing element after reassigning talent
bird name changed!
['dance']
bird
['walk']
bird
['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
['fly']
['fly']
--------------------
after changing attribute
['walk']
['fly']
--------------------
assign to another attribute and change it
['swim']
['swim']
--------------------

由于對象屬性就算內容完全一樣(剛初始化后的屬性內容一般都是一樣的),也會分配到完全不同的內存地址上去。所以不存在「同類對象之間影響」的情況。

但如果讓一個對象的屬性和另一個對象的屬性指向同一個地址,兩者之間(但也僅限兩者之間)便又互相牽連起來。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 镇巴县| 曲水县| 奉贤区| 会同县| 望奎县| 曲麻莱县| 菏泽市| 喜德县| 大厂| 东丽区| 甘南县| 含山县| 那曲县| 阳谷县| 博爱县| 龙南县| 滦平县| 南木林县| 抚顺县| 兰坪| 古丈县| 读书| 团风县| 东乡族自治县| 密山市| 江源县| 平顶山市| 景洪市| 荣昌县| 福泉市| 呼伦贝尔市| 盐源县| 鹤壁市| 富宁县| 章丘市| 西吉县| 赞皇县| 宁海县| 横峰县| 安丘市| 进贤县|