Python進階之高級面向?qū)ο缶幊蹋ㄈ?/h1>

本篇主要介紹面向?qū)ο蟾呒売梅ㄉ髁辍㈠e誤處理以及文件讀寫。

多繼承

Python 中繼承多個類用逗號隔開喻奥,示例如下所示:

class Dog(Animal, Runnable):
    pass

Tips:

  • 多重繼承席纽,子類可以獲得父類的所有功能;
  • 一般地,Python 中主線都是 單一繼承映凳,若需要 “額外的功能”胆筒,如 Runnable 類似 Java 接口之類的多繼承,把這種設計稱為 MixIn .
  • Python 中允許使用多重繼承诈豌,MixIn 是一種常見的設計仆救。
slots

我們知道 Python 中可以給對象動態(tài)添加 屬性字段,如果要限制實例綁定屬性該如何實現(xiàn)呢矫渔?使用 _slot_ 彤蔽,示例代碼如下:

class Student(object):
    # 用 tuple 定義允許綁定的屬性名稱
    __slots__ = ('name', 'age')

幾點說明:

  • 定義 class 時使用特殊變量 slots 限制 class 實例能添加的屬性;
  • 若給實例動態(tài)綁定 沒在slots 中聲明的屬性庙洼,會拋出異常:AttributeError顿痪;
  • slots 定義的屬性僅對當前類 的實例起作用镊辕,對繼承的子類無用;
  • 若在子類中定義 slots 蚁袭,則子類允許定義的屬性就是 自身的slots + 父類的slots .
定制類

定義:類似 實現(xiàn)len() 方法征懈,讓 class 能作用于 len() 函數(shù),像 len() 這樣特殊用途的函數(shù)揩悄,可以定制類卖哎。

常見的有如下幾種函數(shù)來定制類,可當做是重寫了 object 父類的一些方法:


定制類函數(shù).png
枚舉類

一般地删性,定義常量可以用大寫字母通過整數(shù)定義亏娜,如:JAN = 1,這種寫法簡單蹬挺,但基于類型是 int 型并且仍是變量维贺,值可改變。
未解決上述問題巴帮,為上述枚舉定義一個 class 類型溯泣,每個常量都是 class 的唯一實例。
Python 中提供 Enum 類來實現(xiàn)該功能晰韵。
示例代碼如下:

from enum import Enum, unique

# 1. 定義 Week 枚舉類
Week = Enum('Week', ('Mon', 'Tue', 'Wen', 'Thu', 'Fri', 'Sat', 'Sun'))

# 獲取一個常量
# 打臃⑶恰:Week.Mon = Week.Mon 1
print('Week.Mon =', Week.Mon, Week.Mon.value)

# 枚舉所有成員
for name, member in Week.__members__.items():
    print(name, '=>', member, ',', member.value)

# 打印結(jié)果如下:
# Mon => Week.Mon , 1
# Tue => Week.Tue , 2
# Wen => Week.Wen , 3
# Thu => Week.Thu , 4
# Fri => Week.Fri , 5
# Sat => Week.Sat , 6
# Sun => Week.Sun , 7

# 枚舉說明:
# 1) value 屬性時自動賦給成員的 int 常量,默認從 1 開始計數(shù)雪猪;
# 2)若需要更精確地控制枚舉類型栏尚,可以從 Enum 派生出自定義類。

# 2. 自定義枚舉派生類
# 導入 from enum import Enum, unique 只恨,@unique裝飾器可以保證無重復值

@unique
class Weekday(Enum):
    Sun = 0
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 6

# 不通方式獲取枚舉常量:一是成員名稱译仗,二是直接根據(jù) value 值獲取。
print('day1 =', Weekday.Mon)             # day1 = Weekday.Mon
print('day2 =', Weekday['Tue'])          # day2 = Weekday.Tue
print('day3 =', Weekday(3))              # day3 = Weekday.Wed
print('day4.value =', Weekday(4).value)  # day4.value = 4
print('day5.value =', Weekday.Fri.value) # day5.value = 5

# 遍歷所有枚舉值
for name, member in Weekday.__members__.items():
    print(name, '=>', member)

# 打印結(jié)果如下:
# Sun => Weekday.Sun
# Mon => Weekday.Mon
# Tue => Weekday.Tue
# Wed => Weekday.Wed
# Thu => Weekday.Thu
# Fri => Weekday.Fri
# Sat => Weekday.Sat

總結(jié): Enum 可以把一組相關常量定義在一個 class 中官觅,且 class 不可變纵菌,而且成員可以直接比較。

錯誤&調(diào)試

Python 中使用 try...except...raise...else...finally... 語句進行錯誤處理休涤。先用一段代碼說明如何使用這種錯誤處理機制咱圆。

mport logging

class MyDivideError(ValueError):
    pass

def try_test():
    try:
        print('try...')
        r = 10 / 0
        print('result:', r)
    except ZeroDivisionError as e:
        print('catching error:', e)
        logging.exception(e)
        raise MyDivideError('invalid value: 0')
    else:
        print('no erro ! will be executed when there are no errors!')
    finally:
        print('finally... will always be executed whenever catching errors!')
    
try_test()

# 打印結(jié)果如下:
# try...
# catching error: division by zero
# finally... will always be executed whenever catching errors!
# 異常捕獲后拋出打印結(jié)果:
# __main__.MyDivideError: invalid value: 0

使用說明:
1)try 代碼塊防止代碼出錯,出錯后使用 except 代碼塊捕獲功氨,若沒有錯誤則執(zhí)行 else語句序苏;若想將錯誤拋給外層處理則使用 raise 拋出異常;finally 語句塊不管有沒有發(fā)生錯誤均會執(zhí)行該語句塊捷凄。
2)except 代碼塊同于 catch忱详,若錯誤類型包含父子關系廊遍,則父類會捕獲該錯誤枷踏;所有的錯誤類型都繼承 BaseException。
3)except...else... 發(fā)生了錯誤則執(zhí)行 except 代碼塊及皂,否則執(zhí)行 else 語句偿衰;
4)logging.exception(e) 可以記錄錯誤信息炒刁,便于事后排查仔雷。

單元測試

目前僅以一張簡圖來展示 Python 中單元測試:


單元測試.png

IO編程

文件讀寫

背景:在磁盤上讀寫文件的功能均是由操作系統(tǒng)提供冷溶,現(xiàn)代操作系統(tǒng)不允許普通的程序直接操作磁盤。

方式:讀寫文件就是請求操作系統(tǒng)打開一個文件對象(通常稱為文件描述符)佛点,然后醇滥,通過操作系統(tǒng)提供的接口從這個文件對象中讀取數(shù)據(jù)(讀文件)黎比,或者把數(shù)據(jù)寫入該文件對象(寫文件)超营。

  1. 讀文件
    方法: Python內(nèi)置函數(shù) - open(文件名, 標識符['r'只讀])
    說明:
    1)若文件不存在,該函數(shù)會拋出 IOError 錯誤阅虫,并且給出錯誤碼和詳細信息告知文件不存在演闭;
    2)若文件打開成功,使用 read() 函數(shù)可一次性讀取文件全部內(nèi)容颓帝;
    3)Python 把內(nèi)容讀到內(nèi)存米碰,用一個 str 對象表示。
    4)調(diào)用 close() 方法關閉文件购城。
    Tips: 文件使用完畢必須關閉吕座,因為文件對象會占用操作系統(tǒng)的資源,并且os同一時間能打開的文件數(shù)量是有限的瘪板。
# 以下拋出錯誤:FileNotFoundError: [Errno 2] No such file or directory: 'Users/xss/notfound.txt'
file = open('./channel', 'r')
content = file.read()
file.close()   # 必須關閉文件
print(content) # 打印文件內(nèi)容(success)

完整定義一個讀文件函數(shù):

def readFile(filename):
    try:
        file = open(filename, 'r')
        print(file.read())
    finally:
        if file:
            file.close()

簡潔代碼寫法:

def readFile2(filename):
    with open(filename, 'r') as file:
        print(file.read())

問題:當文件size太大時吴趴,一次性讀取文件,內(nèi)存就會爆滿侮攀,如何解決呢锣枝?
方式:保險起見,三種方式:
1)read(size); 每次讀取一行內(nèi)容兰英,每次最多讀取 size 個字節(jié)的內(nèi)容撇叁;
2)readline(); 每次讀取一行內(nèi)容;
3)readlines(); 一次讀取所有內(nèi)容并按行返回 list.

各方式使用場景:
1)read() 適用于文件很小時一次性讀绕杳场陨闹;
2)無法確定文件大小時,反復調(diào)用 read(size) 比較保險薄坏;
3)若是配置文件趋厉,使用 readlines() 最方便。

def readFileByLine(filename):
    file = open(filename, 'r')
    for line in file.readlines():
        print(line.strip())  # 刪除末尾'\n'
  1. 文件讀取模式
  • 文本文件讀取+默認UTF-8: open(filename, 'r') 颤殴;
  • 二進制文件讀让倮:open(filename, 'rb') # 二進制文件-圖片視頻等;
  • 非UTF-8編碼文件:open(filename, 'r', encoding='gbk') # 中文涵但。

關于文件編碼不規(guī)范問題杈绸,會拋出 UnicodeDecodeError 非法編碼字符帖蔓,使用如下方式:

# f = open('./channel', 'r')
 # print(f.read())

ff = open('./first.py', 'r', encoding='gbk', errors='ignore')
print(ff.read()) # 忽略非法字符,讀取中文亂碼(改成 encoding='utf-8')
  1. 寫文件
    open(filename, 'w' / 'wb') 寫文本文件或?qū)懚M制文件
filename = './first.py'
f = open(filename, 'w')
f.write('# Hello, world')
f.close()

readFileByLine(filename)

def writeFile():
    with open('./first.py', 'w') as f:
        f.write('Hello, world !')

總結(jié): Python 中瞳脓,文件讀寫是通過 open() 函數(shù)打開的文件對象完成的塑娇。使用 with 語句操作文件 IO 是好習慣。

另外還有 StringIO 劫侧、BytesIO埋酬,序列化和JSON內(nèi)置模塊使用,暫用一張圖展示說明:


IO.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

  • 序言:七十年代末烧栋,一起剝皮案震驚了整個濱河市写妥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌审姓,老刑警劉巖珍特,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異魔吐,居然都是意外死亡扎筒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門酬姆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嗜桌,“玉大人,你說我怎么就攤上這事辞色」浅瑁” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵淫僻,是天一觀的道長诱篷。 經(jīng)常有香客問我,道長雳灵,這世上最難降的妖魔是什么棕所? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮悯辙,結(jié)果婚禮上琳省,老公的妹妹穿的比我還像新娘。我一直安慰自己躲撰,他們只是感情好针贬,可當我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拢蛋,像睡著了一般桦他。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谆棱,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天快压,我揣著相機與錄音圆仔,去河邊找鬼。 笑死蔫劣,一個胖子當著我的面吹牛坪郭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播脉幢,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼歪沃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嫌松?” 一聲冷哼從身側(cè)響起沪曙,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎豆瘫,沒想到半個月后珊蟀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡外驱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了腻窒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昵宇。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖儿子,靈堂內(nèi)的尸體忽然破棺而出瓦哎,到底是詐尸還是另有隱情,我是刑警寧澤柔逼,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布蒋譬,位于F島的核電站,受9級特大地震影響愉适,放射性物質(zhì)發(fā)生泄漏犯助。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一维咸、第九天 我趴在偏房一處隱蔽的房頂上張望剂买。 院中可真熱鬧,春花似錦癌蓖、人聲如沸瞬哼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坐慰。三九已至,卻和暖如春用僧,著一層夾襖步出監(jiān)牢的瞬間结胀,已是汗流浹背两残。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留把跨,地道東北人人弓。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像着逐,于是被迫代替她去往敵國和親崔赌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,922評論 2 361

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