Python 簡明教程 --- 19秤涩,Python 類與對象

那些能用計(jì)算機(jī)迅速解決的問題陶舞,就別用手做了。
—— Tom Duff

目錄

上一節(jié) 我們介紹了Python 面向?qū)ο?/code>的相關(guān)概念撑帖,我們已經(jīng)知道類與對象面向?qū)ο缶幊?/code>中非常重要的概念蓉坎。

類就是一個模板,是抽象的胡嘿。對象是由類創(chuàng)建出來的實(shí)例蛉艾,是具體的。由同一個類創(chuàng)建出來的對象擁有相同的方法屬性,但屬性的值可以是不同的伺通。不同的對象是不同的實(shí)例箍土,互不干擾。

1罐监,類的定義

如下吴藻,是一個最簡單的類,實(shí)際上是一個空類弓柱,不能做任何事情:

class People:
    pass

在Python 中定義一個類沟堡,需要用到class 關(guān)鍵字,后邊是類名矢空,然后是一個冒號:航罗,然后下一行是類中的代碼,注意要有縮進(jìn)屁药。

2粥血,創(chuàng)建對象

People 雖然是一個空類,但依然可以創(chuàng)建對象酿箭,創(chuàng)建一個對象的語法為:

對象名 = 類名(參數(shù)列表)

參數(shù)列表是跟__init__ 構(gòu)造方法相匹配的复亏,如果沒有編寫__init__ 方法,創(chuàng)建對象時缭嫡,就不需要寫參數(shù)缔御,如下:

>>> p = People()
>>> p
<__main__.People object at 0x7fd30e60be80>
>>> 
>>> p1 = People()
>>> p1
<__main__.People object at 0x7fd30e60be48>

pp1 都是People類的對象。0x7fd30e60be80p 的地址妇蛀,0x7fd30e60be48p1 的地址耕突。可以看到不同的對象的地址是不同的评架,它們是兩不同的實(shí)例眷茁,互不干擾。

3古程,屬性

類中可以包含屬性類中的變量)蔼卡,創(chuàng)建出來的對象就會擁有相應(yīng)的屬性,每個對象的屬性的值可以不同挣磨。

創(chuàng)建好對象后,可以用如下方法給對象添加屬性:

>>> p = People()
>>> p.name = '小明' # 添加 name 屬性
>>> p.sex = '男'    # 添加 sex 屬性
>>> p.name         # 訪問對象的屬性
'小明'
>>> p.sex          # 訪問對象的屬性
'男'

雖然在技術(shù)上可以這樣做荤懂,但是一般情況下茁裙,我們并不這樣為對象添加屬性,這樣會破壞類的封裝性节仿,使得代碼混亂晤锥,不利于維護(hù)。

當(dāng)訪問一個不存在的屬性時,會出現(xiàn)異常:

>>> p.job         # 一個不存在的屬性
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'People' object has no attribute 'job'

我們一般會在__init__ 方法中為類添加屬性并賦值矾瘾。

4女轿,__init__ 方法

在Python 的類中,以雙下劃線__開頭和結(jié)尾的方法壕翩,被稱為魔法方法蛉迹,每個魔法方法都有特定的含義。Python 為我們規(guī)定了一些魔法方法放妈,讓我們自己實(shí)現(xiàn)這些方法北救。

__init__ 方法叫做構(gòu)造方法,用來初始化對象芜抒。Python 解釋器會在生成對象時珍策,自動執(zhí)行構(gòu)造方法,而無需用戶顯示調(diào)用宅倒。

__init__ 方法不需要有返回值攘宙。

類中的所有實(shí)例方法 方法,都至少有一個參數(shù)拐迁,就是self蹭劈。Python 中的self 相當(dāng)于C++ 和Java 中的this 指針,都是代表當(dāng)前對象唠亚。只是Python 中的self 需要顯示寫在方法的第一個參數(shù)链方,而this 指針則不需要寫在方法參數(shù)中。

構(gòu)造方法一般用于初始化對象的一些屬性灶搜,構(gòu)造函數(shù)可以不寫祟蚀,也可以只有一個self 參數(shù)。

當(dāng)構(gòu)造函數(shù)只有一個self 參數(shù)時割卖,創(chuàng)建該類的對象時前酿,不需要添加參數(shù)。當(dāng)構(gòu)造函數(shù)除了self 參數(shù)還有其它參數(shù)時鹏溯,創(chuàng)建該類的對象時罢维,則需要添加相匹配的參數(shù)。

比如丙挽,我們定義一個People 類肺孵,它有三個屬性,分別是name颜阐,sex平窘,age

class People:

    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age
        print('執(zhí)行了 __init__ 方法')

    def print_info(self):
        print('people:%s sex:%s age:%s' % (
            self.name, self.sex, self.age))

在這個People 類中除了有一個__init__ 方法外,還有一個print_info 方法凳怨,每個方法中的都有self 參數(shù)瑰艘,并且是第一個參數(shù)是鬼,self 代表當(dāng)前對象。

在創(chuàng)建該類的對象時紫新,需要傳遞匹配的參數(shù)(self 參數(shù)不用傳遞):

>>> p = People('小明', '男', 18)
執(zhí)行了 __init__ 方法
>>> p 
<People.People object at 0x7feb6276bda0>
>>> p.print_info()
people:小明 sex:男 age:18
>>>
>>> p1 = People('小美', '女', 18)
執(zhí)行了 __init__ 方法
>>> p1
<People.People object at 0x7fd54352be48>
>>> p1.print_info()
people:小美 sex:女 age:18

可以看到均蜜,在創(chuàng)建pp1 對象時,字符串執(zhí)行了 __init__ 方法 被打印了出來芒率,而我們并沒有顯示調(diào)用該方法囤耳,說明__init__ 方法被默認(rèn)執(zhí)行了。

對象pp1 是兩個不同的對象敲董,擁有相同的屬性和方法紫皇,但是屬性值是不一樣的。兩個對象互不干擾腋寨,對象p 的地址為0x7feb6276bda0聪铺,p1 的地址是0x7fd54352be48

執(zhí)行代碼p.print_info()萄窜,是調(diào)用p 對象的print_info() 方法铃剔,因?yàn)椋诙x該方法的時候查刻,只有一個self 參數(shù)键兜,所以在調(diào)用該方法的時候,不需要有參數(shù)穗泵。

5普气,私有屬性和方法

私有屬性

普通的屬性,就像上面的name佃延,sexage 屬性现诀,都是公有屬性,在類的外部都可以被任意的訪問履肃,就是可以用對象.屬性名的方式來訪問屬性仔沿,如下:

>>> p = People('小明', '男', 18)
執(zhí)行了 __init__ 方法
>>> p.name  # 訪問屬性
'小明'
>>> p.name = '小麗'  # 修改屬性
>>> p.name  # 訪問屬性
'小麗'

這樣就破壞了數(shù)據(jù)的封裝性,這種訪問方式是不可控(會不受限制的被任意訪問)的尺棋,不利于代碼的維護(hù)封锉,不符合面向?qū)ο蟮木幊桃?guī)范。

所以膘螟,通常我們會將類中的屬性成福,改為私有屬性,就是不能以對象.屬性名 這樣的方式訪問類屬性荆残。

在Python 中闷叉,通過在屬性名的前邊添加雙下劃線__,來將公有屬性變?yōu)?code>私有屬性脊阴,如下:

#! /usr/bin/env python3

class People:

    def __init__(self, name, sex, age):
        self.__name = name   # 兩個下劃線
        self.__sex = sex     # 兩個下劃線
        self._age = age      # 一個下劃線
        print('執(zhí)行了 __init__ 方法')

    def print_info(self):
        print('people:%s sex:%s age:%s' % (
            self.__name, self.__sex, self._age))

這樣就無法通過對象.屬性名的方式來訪問屬性了,如下:

>>> p = People('小美', '女', 18)
執(zhí)行了 __init__ 方法
>>> p.__name        # 出現(xiàn)異常
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'People' object has no attribute '__name'

但是,Python 中這種私有屬性的方式嘿期,并不是真正的私有屬性品擎,Python 只是將__name 轉(zhuǎn)換為了_People__name,即是在__name 的前邊加上了_類名(_People)备徐,我們依然可以這樣訪問__name 屬性:

>>> p._People__name
'小美'

但我們并不提倡這種方式萄传,這會讓代碼變得混亂難懂。

可以注意到蜜猾,People 類中的_age 屬性是以單下劃線開頭的秀菱,這種以單下劃線開頭的屬性是可以在類的外部被訪問的:

>>> p._age
18

但是根據(jù)Python 規(guī)范,以單下劃線開頭的屬性蹭睡,也被認(rèn)為是私有屬性衍菱,也不應(yīng)該在類的外部訪問(雖然在技術(shù)上是可以訪問的)。

注意:以雙下劃線__ 開頭且結(jié)尾的屬性__xxx__肩豁,是特殊屬性脊串,是公有的,可在類的外部訪問

私有方法

私有方法與私有屬性類似清钥,也可以在方法名的前邊加上雙下劃線__琼锋,來將某個方法變成私有的,一般不需要被外部訪問的方法祟昭,應(yīng)該將其設(shè)置為私有方法缕坎。

6,setget 方法

為了數(shù)據(jù)的封裝性篡悟,我們不應(yīng)該直接在類的外部以對象.屬性名的方式訪問屬性谜叹,那么如果我們需要訪問類的屬性該怎么辦呢?

這時我們需要為每個私有屬性都提供兩個方法:

  • set 方法:用于設(shè)置屬性的值
  • get 方法:用于訪問屬性的值

為了減少代碼量恰力,這里只為__name 屬性設(shè)置了這兩個方法叉谜,代碼如下:

#! /usr/bin/env python3

class People:

    def __init__(self, name, sex, age):
        self.__name = name
        self.__sex = sex
        self._age = age
        print('執(zhí)行了 __init__ 方法')

    def print_info(self):
        print('people:%s sex:%s age:%s' % (
            self.__name, self.__sex, self._age))

    # set 和 get 方法
    def set_name(self, name):
        self.__name = name

    def get_name(self):
        return self.__name

用戶可以這樣設(shè)置和訪問類的屬性:

>>> from People import People
>>> p = People('小美', '女', 18)
執(zhí)行了 __init__ 方法
>>> p.get_name()         # 獲取 name 值
'小美'
>>> p.set_name('小麗')   # 設(shè)置新的值
>>> p.get_name()        # 再次獲取name 值
'小麗'

(完。)


推薦閱讀:

Python 簡明教程 ---14踩萎,Python 數(shù)據(jù)結(jié)構(gòu)進(jìn)階
Python 簡明教程 ---15停局,Python 函數(shù)
Python 簡明教程 ---16,Python 高階函數(shù)
Python 簡明教程 ---17香府,Python 模塊與包
Python 簡明教程 ---18董栽,Python 面向?qū)ο?/a>

  • 序言:七十年代末,一起剝皮案震驚了整個濱河市企孩,隨后出現(xiàn)的幾起案子锭碳,更是在濱河造成了極大的恐慌,老刑警劉巖勿璃,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擒抛,死亡現(xiàn)場離奇詭異推汽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)歧沪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門歹撒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诊胞,你說我怎么就攤上這事暖夭。” “怎么了撵孤?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵迈着,是天一觀的道長。 經(jīng)常有香客問我邪码,道長裕菠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任霞扬,我火速辦了婚禮糕韧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘喻圃。我一直安慰自己萤彩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布斧拍。 她就那樣靜靜地躺著雀扶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肆汹。 梳的紋絲不亂的頭發(fā)上愚墓,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機(jī)與錄音昂勉,去河邊找鬼浪册。 笑死,一個胖子當(dāng)著我的面吹牛岗照,可吹牛的內(nèi)容都是我干的村象。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼攒至,長吁一口氣:“原來是場噩夢啊……” “哼厚者!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起迫吐,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤库菲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后志膀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體熙宇,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鳖擒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了奇颠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片败去。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖烈拒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情广鳍,我是刑警寧澤荆几,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站赊时,受9級特大地震影響吨铸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜祖秒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一诞吱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竭缝,春花似錦房维、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至湿故,卻和暖如春阿趁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背坛猪。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工脖阵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人墅茉。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓命黔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親躁锁。 傳聞我的和親對象是個殘疾皇子纷铣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容