Python 類(Class)

類(Class)


關(guān)于類(Class)叉讥,是一個(gè)很抽象的概念测蹲。本篇幅簡單介紹關(guān)于類的一些基礎(chǔ)內(nèi)容像屋。更多深入的內(nèi)容,可詳閱官方文檔:

https://docs.python.org/3/tutorial/index.html

在 Python 中电禀,所有的數(shù)據(jù)類型都可以視為對象幢码,也可以自定義對象。自定義對象數(shù)據(jù)類型就是類(Class)的概念尖飞。

Python 的類提供了面向?qū)ο缶幊痰乃袠?biāo)準(zhǔn)特性:類繼承機(jī)制允許多個(gè)基類症副,派生類可以覆蓋基類的任何方法,一個(gè)方法可以調(diào)用基類中相同名稱的方法政基。

類定義語法


最簡單的類定義的語法如下:

class ClassName:
    <statement-1>
    .
    .
    .
    <statement-N>

類定義贞铣,和函數(shù)定義類似,必須定義執(zhí)行后才能生效沮明。

類對象


類對象支持兩種操作:屬性引用和實(shí)例化辕坝。

這里的屬性引用使用的是 Python 中所有屬性引用的標(biāo)準(zhǔn)語法:obj.name。有效的屬性名稱是類對象被創(chuàng)建存在于類命名空間的所有名稱荐健。假設(shè)酱畅,類定義如下:

class MyClass:
    """A simple example class"""
    i = 123
    
    def func(self):
        return "hello world"

在這里 MyClass.iMyclass.func 屬于有效屬性,分別返回一個(gè)整數(shù)和一個(gè)函數(shù)對象江场。類屬性可以被賦值纺酸,所以也可以通過賦值改變 MyClass.i 的值。在這里 __doc__ 也是一個(gè)有效的屬性址否,它返回的是一個(gè)所屬類的文檔字符串:"A simple example class"餐蔬。

類的實(shí)例化使用函數(shù)表示法。例如,沿用上面的類:

x = MyClass()

創(chuàng)建類的實(shí)例樊诺,并將此對象賦值給變量 x仗考。在這個(gè)實(shí)例化操作的過程中,創(chuàng)建的是一個(gè)空對象啄骇。但許多類喜歡創(chuàng)建帶特定初始狀態(tài)的自定義實(shí)例。因此瘟斜,一個(gè)類能夠定義一個(gè)特殊的方法:__init__()缸夹,例如:

def __init__(self):
    self.data = []

如果一個(gè)類定義了 __init__() 方法,創(chuàng)建新的實(shí)例的時(shí)候螺句,會自動調(diào)用該方法虽惭。

當(dāng)然,這個(gè)方法還能夠有額外的參數(shù)蛇尚。在這種情況下芽唇,提供給類實(shí)例化的參數(shù)都會傳遞給 __init__(),例如:

>>> class Student:
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age
...
>>> s = Student('demon', 21)

>>> s.name, s.age
('demon', 21)

實(shí)例對象


從屬性引用來理解實(shí)例對象取劫。兩種有效的屬性名稱包括:數(shù)據(jù)屬性和方法匆笤。

數(shù)據(jù)屬性不需要聲明:它會像局部變量一樣,在首次賦值的時(shí)候產(chǎn)生谱邪。

另一種實(shí)例屬性引用稱為方法炮捧。方法是從屬于對象的函數(shù)。(方法并非類實(shí)例所特有的惦银,其他對象也有方法咆课。本篇幅若無特別說明,方法一詞專指類實(shí)例對象的方法)

實(shí)例對象的有效方法名稱依賴于所屬的類扯俱。根據(jù)定義书蚪,一個(gè)類所有為對象的屬性都定義了與實(shí)例的相應(yīng)方法。

在上面自定義的 MyClass 類中迅栅,x.func 是有效的方法引用殊校,因?yàn)?MyClass.func 是一個(gè)函數(shù),而 x.i 并不是方法读存,因?yàn)?MyClass.i 并不是一個(gè)函數(shù)箩艺。但 x.func 并不是就等同于 MyClass.func,因?yàn)?x.func 是一個(gè)方法對象宪萄,不是函數(shù)對象艺谆。

方法對象


在上面 MyClass 的例子中,執(zhí)行下面的語句:

x.func()

這個(gè)時(shí)候回返回 hello world拜英。但是静汤,當(dāng)不想馬上就調(diào)用方法時(shí),因?yàn)?`x.func

` 是一個(gè)方法對象,可以將其賦值給一個(gè)變量虫给,等待后面調(diào)用藤抡。

xf = x.func
print(xf())

當(dāng)執(zhí)行 print 語句時(shí),同樣會返回 hello world抹估。

將前面的例子重新放到這里:

class MyClass:
    """A simple example class"""
    i = 123
    
    def func(self):
        return "hello world"

x = MyClass()

在前面執(zhí)行 x.func() 的時(shí)候缠黍,這里并沒有帶參數(shù),但是在 func 的函數(shù)定義時(shí)药蜻,指定了一個(gè) self 參數(shù)瓷式。

這就是方法特殊的地方,實(shí)例對象會作為函數(shù)的第一個(gè)參數(shù)被傳入语泽。其實(shí)調(diào)用 x.func 等同于 MyClass.func(x)贸典。

類和實(shí)例變量


一般來說,實(shí)例變量用于每個(gè)實(shí)例的唯一數(shù)據(jù)踱卵,類變量用于類的所有實(shí)例共享的屬性和方法廊驼,如下實(shí)例:

class Dog:
    # 類變量,用于所有實(shí)例共享
    kind = 'canine'

    def __init__(self, name):
        # 實(shí)例變量惋砂,每個(gè)實(shí)例專有
        self.name = name

>>> d = Dog('Emy')
>>> e = Dog('Buddy')
>>> d.kind
'canine'
>>> e.kind
'canine'
>>> d.name
'Emy'
>>> e.name
'Buddy'

由上面的例子可以看出妒挎, kind 類變量是所有實(shí)例共有的,而實(shí)例變量 name 則是每個(gè)實(shí)例獨(dú)有的西饵。

需要注意的是饥漫,共享的數(shù)據(jù)若是涉及到可變對象,往往得到的結(jié)果并不是期望的結(jié)果罗标。例如:

class Dog:

    tricks = []

    def __init__(self, name):
        self.name = name
    
    def add_tricks(self, trick):
        self.tricks.append(trick)

>>> d = Dog('Emy')
>>> e = Dog('Buddy')
>>> d.add_tricks('roll over')
>>> e.add_tricks('play dead')
>>> d.tricks
['roll over', 'play dead']
>>> e.tricks
['roll over', 'play dead']

在這里可以看出庸队,列表不應(yīng)該被用作類變量。正確的類設(shè)計(jì)應(yīng)該使用實(shí)例變量:

class Dog:

    def __init__(self, name):
        self.name = name
        self.tricks = []
    
    def add_tricks(self, trick):
        self.tricks.append(trick)

>>> d = Dog('Emy')
>>> e = Dog('Buddy')
>>> d.add_tricks('roll over')
>>> e.add_tricks('play dead')
>>> d.tricks
['roll over']
>>> e.tricks
['play dead']

注意事項(xiàng): 數(shù)據(jù)屬性會覆蓋具有相同名稱的方法屬性闯割。若是程序當(dāng)中的代碼量夠大彻消,這種情況很有可能會發(fā)生。所以可以做某些約定來最小化這種可能產(chǎn)生沖突的情況宙拉。例如在屬性名稱前加一個(gè)下劃線宾尚,或者方法屬性用動詞來命名,名詞來命名數(shù)據(jù)屬性谢澈。


以上就是關(guān)于類(Class)的一部分基礎(chǔ)內(nèi)容煌贴,后續(xù)會另開篇幅繼續(xù)介紹類的其他相關(guān)內(nèi)容。


歡迎關(guān)注微信公眾號《書所集錄》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锥忿,一起剝皮案震驚了整個(gè)濱河市牛郑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敬鬓,老刑警劉巖淹朋,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笙各,死亡現(xiàn)場離奇詭異,居然都是意外死亡础芍,警方通過查閱死者的電腦和手機(jī)杈抢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仑性,“玉大人惶楼,你說我怎么就攤上這事≌锔耍” “怎么了歼捐?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長刽辙。 經(jīng)常有香客問我窥岩,道長甲献,這世上最難降的妖魔是什么宰缤? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮晃洒,結(jié)果婚禮上慨灭,老公的妹妹穿的比我還像新娘。我一直安慰自己球及,他們只是感情好氧骤,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吃引,像睡著了一般筹陵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镊尺,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天朦佩,我揣著相機(jī)與錄音,去河邊找鬼庐氮。 笑死语稠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的弄砍。 我是一名探鬼主播仙畦,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼音婶!你這毒婦竟也來了慨畸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤衣式,失蹤者是張志新(化名)和其女友劉穎先口,沒想到半個(gè)月后型奥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碉京,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年厢汹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谐宙。...
    茶點(diǎn)故事閱讀 40,427評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烫葬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凡蜻,到底是詐尸還是另有隱情搭综,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布划栓,位于F島的核電站兑巾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏忠荞。R本人自食惡果不足惜蒋歌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望委煤。 院中可真熱鬧堂油,春花似錦、人聲如沸碧绞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽讥邻。三九已至迫靖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間兴使,已是汗流浹背系宜。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鲫惶,地道東北人蜈首。 一個(gè)月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像欠母,于是被迫代替她去往敵國和親欢策。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評論 2 359