小牛叔帶你飛越類的門檻
其中我們已知道定義變量在類中就表示為屬性。但是在不同的位置定義變量會有不同的作用,并且采用不同的命名方式,也會讓變量具有不同的作用
本文假設(shè)有一個類指南針(compass),可想象成某個地圖游戲中幫助主角尋找方向,也是本節(jié)主要的示例。
1. 類屬性與實例屬性
compass類的定義如下代碼:
1 class Compass: 2 invitedBy = '中國' 3 usedFor ='導(dǎo)航' 4 #初始化方法 5 def __init__(self): 6 self.shape = 'round'
?
1.1 類屬性
可以看到和Bread不同,Compass類定義了2個變量分別是invitedBy發(fā)明者,usedFor用處。都是類屬性,這2個變量(即類屬性)代表的意義,歸所有“指南針”同時具有的,它們的值與“類”實例化出的“實例”無關(guān)。在面向?qū)ο笾校堰@樣的變量叫做類屬性(也可以叫類變量、靜態(tài)變量)。
類屬性定義完成后也通過“實例名.變量名”的形式進行讀取數(shù)值,如下語句所示:
com1,com2 = Compass(),Compass() print(com1.invitedBy,com2.invitedBy)
?
運行的結(jié)果是:
中國 中國
如類屬性需要改變值,必須通過“類名.變量名”這樣的形式進行賦值,請參看下面的代碼把這兩個屬性值改成英文表達:
Compass.invitedBy = 'CN' print(com1.invitedBy,com2.invitedBy)
?
上面代碼改變了類變量的值,但從Compass類實例化出來的所有的實例的值都會改變,運行結(jié)果如下:
中國 中國
CN CN
需要說明的是,類屬性無法通過“實例.變量名”這種形式賦值的,如果你這樣做了,Python是會根據(jù)規(guī)則做出誤判斷,認為這種形式的賦值是給“實例屬性”賦值,而不是“類屬性”。系統(tǒng)并不會出錯,只會產(chǎn)生一個與類屬性相同名稱的實例屬性名,從而把同名的類屬性給“覆蓋”掉,繼續(xù)在上面的語句后面添加如下的語句:
com1.invitedBy = 'Korean' print(com1.invitedBy,com1.__class__.invitedBy,com2.invitedBy)
?
上面語句中,使用了“特殊變量”__class__,它指向該實例的類。通過如下對比一下第2句顯示的2個值有什么不同。
com1.invitedBy:指的是com1實例的invitedBy屬性,可以是“實例屬性”也可以是“類屬性”,但“實例屬性”優(yōu)先。
com1.__class__.invitedBy:__class__變量會返回實例的類,因此invitedBy一定表示“類變量”。把com1實例的“類變量”invitedBy“錯誤”賦值后,再看看會不會產(chǎn)生“覆蓋的效果”,整個程序的運行結(jié)果如下:
中國 中國
CN CN
Korean CN CN
看到如果企圖通過實例來對“類屬性”進行賦值Korean,只會新創(chuàng)建該實例屬性并且賦于新值Korean,并且這個值只會覆蓋企圖通過“實例名.類變量名”方式來取得類屬性的值。
對于“類屬性”,我們一般把類的通用的屬性、共同的數(shù)據(jù)或是需要集中的數(shù)據(jù),通過類變量的方式存儲,這樣就可以操作實例共同的屬性或是方便批量操作。
比如使用類Student來管理學(xué)生信息,一般會把學(xué)生的成績數(shù)據(jù)庫,存儲在類變量(類屬性)里,這樣操作員只要訪問類,就可以取得所有同學(xué)的成績。
1.2 私有變量
在進行類定義時,可以定義某些變量只能在類的內(nèi)部使用,外部無法使用的,稱之為私有變量。要聲明私有變量,使用2個下劃線開頭來進行命名,比如指南針實例有一個私有變量__magnetism記錄了指針的磁性,這個數(shù)據(jù)一般不使用,但是可能在實現(xiàn)內(nèi)部功能的時候會有用處。如下:
class Compass: invitedBy = '中國' usedFor ='導(dǎo)航' #初始化方法 def __init__(self): self.shape = 'round' self.__ magnetism = 4
?
上面代碼定義了實例屬性shape形狀,默認值是round(圓形),定義了“私有變量”__magnetism設(shè)置為4,用來表示指針的磁力。試試從“外部”來訪問這個私有變量能不能訪問成功:
com1,com2 = Compass(),Compass() print(com1.__ magnetism)
?
這時系統(tǒng)運行的結(jié)果出錯,出錯信息如下:
AttributeError: 'Compass' object has no attribute '__magnetism’
中文意思為:屬性錯誤“Compass”對象沒有__magnetism的屬性。
由于私有變量不能被外部訪問,這種機制起到了保護變量的作用,但它的值并不是不能改變的,可以把設(shè)置私有變量的活交給普通的類內(nèi)部的方法。如下:
def setMag(self,mag_level=4): self.__magnetism = mag_level
?
上面setMag的方法就完成了設(shè)置私有變量的值的任務(wù),上例當中私有變量__magnetism用來反饋指針的磁性,只要指針可以正常工作一般不太關(guān)心它的值,但如果這個值太小,就會造成指南針根本無法工作,人們更加關(guān)心的是指南針能否正常工作。所以有一個返回工作狀態(tài)的方法,寫法如下:
def getStatus(self): return self.__magnetism>=1 if "正常" else "失效"
?
PS: 代碼結(jié)尾返回“三元運算”表達式,當磁性大于等于1時,返回工作狀態(tài)為“正?!保駝t就返回“失效”。
看看這個私有變量能否正常的工作,所有的程序如下:
class Compass: invitedBy = '中國' usedFor ='導(dǎo)航' #初始化方法 def __init__(self): self.shape = 'round' self.__magnetism = 4 def setMag(self,mag_level=4): self.__magnetism = mag_level def getStatus(self): return "正常" if self.__magnetism>=1 else "失效" com1,com2 = Compass(),Compass() com1.setMag(1) com2.setMag(0.5) print(com1.getStatus(),com2.getStatus()) #下面的語名會出錯 print(com1.__magnetism)
?
在上面的程序里,最后1行我們試圖訪問類的私有變量,因此會出錯。如下:
正常 失效 Traceback (most recent call last): File "/Users/…/books/第7章 類和對象/7.4.2 類內(nèi)部變量.py", line 18, in <module> print(com1.__magnetism) AttributeError: 'Compass' object has no attribute '__magnetism'
?
從運行結(jié)果的第1行看,把2個指南針的磁性分別設(shè)置成1和0.5,就會分別得出正常和失效的狀態(tài),程序的前半部分運行成功。
此處稍作延伸,編寫類的“方法”時,即類中定義的函數(shù),也有一類叫私有函數(shù),其命名的方式就是以兩個下劃線開頭__MethodName()。這部分的內(nèi)容同學(xué)們可以自行學(xué)習,因為后面不會用到。文章來源:http://www.zghlxwxcb.cn/news/detail-767411.html
最后,同學(xué)們應(yīng)該了解一下私有變量的實現(xiàn)的原理。在Python當中,默認所有的變量與方法都是外部可訪問的,在內(nèi)部為了實現(xiàn)私有變量的功能,比如在類cls下定義了一個私有變量__a,系統(tǒng)在運行的時候會把這個變量改寫成_cls__a,即單劃線+“類名”+私有變量名。如果你知道了,試試看本例中你想從外部顯示__ magnetism的值真正應(yīng)該寫什么樣的語句?文章來源地址http://www.zghlxwxcb.cn/news/detail-767411.html
類本身具有比較復(fù)雜的性質(zhì),收藏本文章,可以今后慢慢學(xué)習吧!小牛叔與你共同進步!
到了這里,關(guān)于Python趣味入門13:類中的各種變量的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!