第五天 函數(shù)和面向?qū)ο?2)
今天主要學(xué)習(xí)面向?qū)ο蟮娜筇卣鳎悍庋b掩宜、繼承蔫骂、多態(tài)以及簡單的設(shè)計模式和模塊化。學(xué)習(xí)項目及練習(xí)源碼地址:GitHub源碼
面向?qū)ο蟮娜筇卣?/h2>
object類
object類是所有類的父類牺汤,因此所有的類都有object類的屬性和方法辽旋。類定義中沒有指定父類,則默認(rèn)父類是object類。
封裝
隱藏對象的屬性和實現(xiàn)細(xì)節(jié)补胚,外提供必要的方法码耐。相當(dāng)于將“細(xì)節(jié)封裝起來”,只對外暴露“相關(guān)調(diào)用方法”溶其。通過Python的“私有屬性骚腥、私有方法”的方式,來實現(xiàn)“封裝”瓶逃。Python沒有嚴(yán)格的語法級別的“訪問控制符”束铭,更多的是依靠程序員自覺實現(xiàn)。
繼承
繼承可以讓子類具有父類的特性厢绝,提高了代碼的重用性契沫。
從設(shè)計上是一種增量進(jìn)化,原有父類設(shè)計不變的情況下昔汉,可以增加新的功能懈万,或者改進(jìn)已有的算法(重寫也叫重載父類的方法)。
-
語法
class 子類類名(父類 1[靶病,父類 2钞速,...]): 類體
定義子類時,必須在其構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù)嫡秕。
子類繼承了父類除構(gòu)造方法之外的所有成員(包括屬性和方法)渴语。
子類可以重新定義父類中的方法,這樣就會覆蓋父類的方法昆咽,也稱為“重寫“
子類中可以通過super關(guān)鍵字調(diào)用父類的方法
可以使用類方法mro()或類屬性mro獲取其層次
內(nèi)置函數(shù)dir()驾凶,可以方便的看到指定對象所有的屬性和方法
對象方法:__str__()用于返回一個對于“對象的描述”,對應(yīng)于內(nèi)置函數(shù)str()掷酗,內(nèi)置函數(shù)print()就是調(diào)用對象的這個方法的返回值调违。
-
看語法,Python是支持多重繼承的
class Parent: def __init__(self,name): self.name = name print("call parent init.") def say_name(self): print('My Name Is:',self.name) class Children(Parent): def __init__(self,name,age): self.age = age Parent.__init__(self,name) # 此處不可以用super().__init__代替 def say_age(self): print("I am a children,my age is:",self.age) def say_name(self): print("I am a children,my name is:",self.name) p = Parent("父親") c = Children("孩子",18) p.say_name() c.say_name() c.say_age() print(p) print(c) print(type(p)) print(type(c)) print(Children.mro()) ''' 輸出結(jié)果如下: call parent init. call parent init. My Name Is: 父親 I am a children,my name is: 孩子 I am a children,my age is: 18 <__main__.Parent object at 0x10bf69ed0> <__main__.Children object at 0x10bfcb1d0> <class '__main__.Parent'> <class '__main__.Children'> [<class '__main__.Children'>, <class '__main__.Parent'>, <class 'object'>] '''
多態(tài)
多態(tài)(polymorphism)是指同一個方法調(diào)用由于對象不同可能會產(chǎn)生不同的行為泻轰。
多態(tài)是方法的多態(tài)技肩,屬性沒有多態(tài)
-
多態(tài)的存在有 2 個必要條件:繼承、方法重寫浮声。
class Car: def __init__(self): print('make a car') def honk(self): print('喇叭滴滴滴') class BWM(car): def __init__(self): print('make a BWM car') Car.__init__(self) def honk(self): print('寶馬來了請閃開') class BYD(Car): def __init__(self): print('make a BYD car') Car.__init__(self) def honk(self): print('BYD正在向你靠近') def honk(car): if isinstance(car,Car): car.honk() else: print("沒車別嗶嗶嗶") bwm = BWM() byd = BYD() honk(bwm) honk(byd) honk(None)
簡單的設(shè)計模式
什么是設(shè)計模式虚婿?
前人總結(jié)的一系列解決各種場景問題的套路。
工廠模式
顧名思義:所謂工廠模式就是一個對象根據(jù)調(diào)用參數(shù)的不同泳挥,可以生產(chǎn)許多不同的對象然痊。
class StarFactory:
def __init__(self):
print("歡迎使用明星工廠")
def createStar(self,name):
if name == 'man':
return ManStar()
elif name == "womam":
return WomanStar()
class ManStar:
def __init__(self):
print("我是一名超級男明星")
class WomanStar:
def __init__(self):
print("我是一名超級女明星")
單列模式
單例模式(Singleton Pattern)的核心作用是確保一個類只有一個實例,并且提供一個訪問該實例的全局訪問點屉符。單例模式只生成一個實例對象剧浸,減少了對系統(tǒng)資源的開銷锹引。當(dāng)一個對象的產(chǎn)生需要比較多的資源,如讀取配置文件唆香、產(chǎn)生其他依賴對象時嫌变,可以產(chǎn)生一個“單例對象”,然后永久駐留內(nèi)存中躬它,從而極大的降低開銷腾啥。
使用new方法
-
類實例對象在Python的模塊時是天然的單例模式
class Singleton: __obj = None __hasInited = False def __init__(self,name): print("try init....") self.name = name if Singleton.__hasInited == False: Singleton.__hasInited = True def __new__(cls, *args, **kwargs): if cls.__obj == None: cls.__obj = object.__new__(cls) return cls.__obj def say_name(self): print(self.name) a = Singleton("a") b = Singleton("b") print(a) print(b) a.say_name() b.say_name() ''' try init.... try init.... <__main__.Singleton object at 0x10882dad0> <__main__.Singleton object at 0x10882dad0> b 這里不是a,說明第二次改變了第一次對象的值虑凛,是一個坑 b '''
模塊和包
使用模塊化編程便于將一個任務(wù)分解成多個模塊碑宴,實現(xiàn)團隊協(xié)同開發(fā)软啼,完成大規(guī)模程序桑谍。實現(xiàn)代碼復(fù)用和可維護性。
模塊
一個模塊對應(yīng)python源文件祸挪,一般后綴名是:.py
-
標(biāo)準(zhǔn)庫模塊
Python 標(biāo)準(zhǔn)庫提供了操作系統(tǒng)功能锣披、網(wǎng)絡(luò)通信、文本處理贿条、文件處理雹仿、數(shù)學(xué)運算等基 本的功能。比如:random(隨機數(shù))整以、math(數(shù)學(xué)運算)胧辽、time(時間處理)、file(文件處理)公黑、os(和操作系統(tǒng)交互)邑商、sys(和解釋器交互)等。
第三方模塊
用戶自動模塊
導(dǎo)入模塊
-
import語句
import 模塊名 # 導(dǎo)入一個模塊 import 模塊 1凡蚜,模塊 2... # 導(dǎo)入多個模塊 import 模塊名 as 模塊別名 # 導(dǎo)入模塊并使用新名字
import加載的模塊分為四個通用類別:
- 使用 python 編寫的代碼(.py文件);
- 已被編譯為共享庫的C人断、C++擴展;
- 包好一組模塊的包
- 使用C編寫并鏈接到python解釋器的內(nèi)置模塊;
-
from...import
from...import 導(dǎo)入的是模塊中的一個函數(shù)/一個類。
動態(tài)導(dǎo)入:內(nèi)置函數(shù)__import__()可以實現(xiàn)動態(tài)導(dǎo)入模塊
使用importlib模塊實現(xiàn)動態(tài)導(dǎo)入
-
每個模塊都有一個名稱朝蜘,通過特殊變量name可以獲取模塊的名稱
一般情況下name輸出模塊名字恶迈,對應(yīng)源文件名。僅有一個例外谱醇,就是當(dāng)一個模塊被作為程序入口時(主程序暇仲、交互式提示符下),它的name的值為“__main__”副渴。我們可以根據(jù)這個特 點熔吗,將模塊源代碼文件中的測試代碼進(jìn)行獨立的處理。
-
當(dāng)導(dǎo)入一個模塊時佳晶,模塊中的代碼都會被執(zhí)行桅狠。如果再次導(dǎo)入這個模塊,不會再次執(zhí)行。
import math print(math.__name__)
包
當(dāng)需要把多個模塊放在一起時中跌,需要就需要用到包了
-
Python中的包就是一個必須有init.py的目錄
- 作為包的標(biāo)識咨堤,不能刪除。
- 用來實現(xiàn)模糊導(dǎo)入
- 導(dǎo)入包實質(zhì)是執(zhí)行init.py文件漩符,可以在init.py文件中做這個包的初始化一喘、以及需要統(tǒng)一執(zhí)行代碼、批量導(dǎo)入嗜暴。
-
導(dǎo)入包
import 包名.模塊名 import 包名.子包名.模塊名 from 包名.模塊名 import 函數(shù)凸克,類,變量
包下面可以包含“模塊(module)”闷沥,也可以再包含“子包(subpackage)”
-
如果是子包內(nèi)的引用萎战,可以按相對位置引入子模塊
from .. import 模塊文件名 # 導(dǎo)入上層目錄中的模塊文件 from . import 模塊文件名 # 導(dǎo)入本層目錄的模塊文件
-
sys.path和模塊搜索路徑
當(dāng)導(dǎo)入某個模塊文件時,Python解釋器一般按照如下路徑尋找模塊文件(按照順序?qū)ふ矣咛樱业郊赐2焕^續(xù)往下尋找):
內(nèi)置模塊
當(dāng)前目錄
程序的主目錄
pythonpath目錄(如果已經(jīng)設(shè)置了pythonpath環(huán)境變量)
標(biāo)準(zhǔn)鏈接庫目錄
第三方庫目錄(site-packages目錄)
-
.pth 文件的內(nèi)容(如果存在的話)
在工程目錄建立這樣一個文件蚂维,一行代表一個目錄
sys.path.append()臨時添加的目錄
安裝第三方庫
pip install 模塊名稱
Python的文件操作
文本文件和二進(jìn)制文件
-
文本文件
文本文件存儲的是普通“字符”文本,python默認(rèn)為unicode字符集(兩個字節(jié)表示一個字符路狮,最多可以表示:65536個)
-
二進(jìn)制文件
二進(jìn)制文件把數(shù)據(jù)內(nèi)容用“字節(jié)”進(jìn)行存儲
文件操作相關(guān)模塊概述
Python標(biāo)準(zhǔn)庫中提供了如下常用文件操作的庫:
名稱 | 說明 |
---|---|
io 模塊 | 文件流的輸入和輸出操作 input output |
os 模塊 | 基本操作系統(tǒng)功能虫啥,包括文件操作 |
glob 模塊 | 查找符合特定規(guī)則的文件路徑名 |
fnmatch 模塊 | 使用模式來匹配文件路徑名 |
fileinput 模塊 | 處理多個輸入文件 |
filecmp 模塊 | 用于文件的比較 |
cvs 模塊 | 用于 csv 文件處理 |
pickle 和 cPickle | 用于序列化和反序列化 |
xml 包 | 用于 XML 數(shù)據(jù)處理 |
bz2、gzip奄妨、zipfile涂籽、zlib、tarfile | 用于處理壓縮和解壓縮文件(分別對應(yīng)不同的算法) |
常用文件操作函數(shù)
-
open()
open(文件名[,打開方式,[encoding="字符編碼"]])
打開方式有如下幾種:
模式 描述 r 讀 read 模式 w f = open(r"filepath","w")砸抛。寫 write模式评雌。如果文件不存在則創(chuàng)建;如果文件存在,則重寫新內(nèi)容; a 追加 append 模式锰悼。如果文件不存在則創(chuàng)建;如果文件存在柳骄,則在文件末尾追加內(nèi)容 b 二進(jìn)制 binary 模式(可與其他模式組合使用) + 讀、寫模式(可與其他模式組合使用)
-
close()
打開的文件對象必須顯式調(diào)用 close()方法 關(guān)閉文件對象箕般。當(dāng)調(diào)用 close()方法時耐薯,首先會把緩沖區(qū)數(shù)據(jù)寫入文件(也可以直接調(diào)用 flush() 方法),再關(guān)閉文件丝里,釋放文件對象曲初。為了確保打開的文件對象正常關(guān)閉,一般結(jié)合異常機制的finally或者with關(guān)鍵字實現(xiàn)無論何種情況都能關(guān)閉打開的文件對象杯聚。
-
write(txt)
把字符串txt寫入到文件中
-
writelines(txtList):
把字符串列表寫入文件中臼婆,不添加換行符
-
with
with關(guān)鍵字(上下文管理器)可以自動管理上下文資源,不論什么原因跳出with塊幌绍,都能確保文件正確的關(guān)閉颁褂,并且可以在代碼塊執(zhí)行完畢后自動還原進(jìn)入該代碼塊時的現(xiàn)場故响。
-
read(size)
從文件中讀取 size 個字符,并作為結(jié)果返回颁独。如果沒有 size 參數(shù)彩届,則讀取整個文件。讀取到文件末尾誓酒,會返回空字符串樟蠕。
-
readline()
讀取一行內(nèi)容作為結(jié)果返回。讀取到文件末尾靠柑,會返回空字符串寨辩。
readlines()
文件讀寫操作練習(xí):測試代碼
os和os.path模塊
os模塊可以幫助我們直接對操作系統(tǒng)進(jìn)行操作。我們可以直接調(diào)用操作系統(tǒng)的可執(zhí)行文件歼冰、命令靡狞,直接操作文件、目錄等等
-
os.system
os.system 可以幫助我們直接調(diào)用系統(tǒng)的命令
import os os.system("ping www.google.com")
-
os.startfile
直接運行可執(zhí)行文件
異常和錯誤處理
python中停巷,引進(jìn)了很多用來描述和處理異常的類耍攘,稱為異常類榕栏。異常類定義中包含了該類異常的信息和對異常進(jìn)行處理的方法畔勤。
如何定位異常
當(dāng)發(fā)生異常時,Python解釋器會報相關(guān)的錯誤信息扒磁,并會在控制臺打印出相關(guān)錯誤信息庆揪。只需按照從上到下的順序即可追溯(Trackback)錯誤發(fā)生的過程,最終定位引起錯誤的那一行代碼妨托。
異常處理語句
-
try...except
try: a = 1/0 except ZeroDivisionError: print("不能除零") except BaseException as e: # 允許多個錯誤捕獲缸榛,更好的控制你的程序 print(e)
-
else
try: a = 1/1 except ZeroDivisionError: print("不能除零") except BaseException as e: # 允許多個錯誤捕獲,更好的控制你的程序 else: print(a) # try里面的沒有錯誤時執(zhí)行 finally: print("無論如何都要執(zhí)行")# 通常用于釋放系統(tǒng)資源
finally
return語句和異常處理問題
在try....except語句中最好不要用return語句兰伤,將它放在try之外内颗。
常見異常匯總
異常名稱 | 說明 |
---|---|
ArithmeticError | 所有數(shù)值計算錯誤的基類 |
AssertionError | 斷言語句失敗 |
AttributeError | 對象沒有這個屬性 |
BaseException | 所有異常的基類 |
DeprecationWarning | 關(guān)于被棄用的特征的警告 |
EnvironmentError | 操作系統(tǒng)錯誤的基類 |
EOFError | 沒有內(nèi)建輸入,到達(dá) EOF 標(biāo)記 |
Exception | 常規(guī)錯誤的基類 |
FloatingPointError | 浮點計算錯誤 |
FutureWarning | 關(guān)于構(gòu)造將來語義會有改變的警告 |
GeneratorExit | 生成器(generator)發(fā)生異常來通知退出 |
ImportError | 導(dǎo)入模塊/對象失敗 |
IndentationError | 縮進(jìn)錯誤 |
IndexError | 序列中沒有此索引(index) |
IOError | 輸入/輸出操作失敗 |
KeyboardInterrupt | 用戶中斷執(zhí)行(通常是輸入^C) |
KeyError | 映射中沒有這個鍵 |
LookupError | 無效數(shù)據(jù)查詢的基類 |
MemoryError | 內(nèi)存溢出錯誤(對于 Python 解釋器不是致命的) |
NameError | 未聲明/初始化對象 (沒有屬性) |
NotImplementedError | 尚未實現(xiàn)的方法 |
OSError | 操作系統(tǒng)錯誤 |
OverflowError | 數(shù)值運算超出最大限制 |
OverflowWarning | 舊的關(guān)于自動提升為長整型(long)的警告 |
PendingDeprecationWarning | 關(guān)于特性將會被廢棄的警告 |
ReferenceError | 弱引用(Weak reference)試圖訪問已經(jīng)垃圾回收了的對象 |
RuntimeError | 一般的運行時錯誤 |
RuntimeWarning | 可疑的運行時行為(runtime behavior)的警告 |
StandardError | 所有的內(nèi)建標(biāo)準(zhǔn)異常的基類 |
StopIteration | 迭代器沒有更多的值 |
SyntaxError | Python 語法錯誤 |
SyntaxWarning | 可疑的語法的警告 |
SystemError | 一般的解釋器系統(tǒng)錯誤 |
SystemExit | 解釋器請求退出 |
TabError | Tab 和空格混用 |
TypeError | 對類型無效的操作 |
UnboundLocalError | 訪問未初始化的本地變量 |
UnicodeDecodeError | Unicode 解碼時的錯誤 |
UnicodeEncodeError | Unicode 編碼時錯誤 |
UnicodeError | Unicode 相關(guān)的錯誤 |
UnicodeTranslateError | Unicode 轉(zhuǎn)換時錯誤 |
UserWarning | 用戶代碼生成的警告 |
ValueError | 傳入無效的參數(shù) |
Warning | 警告的基類 |
WindowsError | 系統(tǒng)調(diào)用失敗 |
ZeroDivisionError | 除(或取模)零 (所有數(shù)據(jù)類型) |
自定義異常類
程序開發(fā)中,有時候我們也需要自己定義異常類敦腔。自定義異常類一般都是運行時異常均澳,通常繼承Exception或其子類即可。命名一般以 Error符衔、Exception為后綴找前。
- 自定義異常由 raise 語句主動拋出
- 練習(xí)自定異常源碼
小結(jié)
到目前為止,Python語言的真實基礎(chǔ)算是告一個段落判族。離登堂入室還有半步飛仙的距離了躺盛。接下來做的就是實戰(zhàn)+實戰(zhàn)+實戰(zhàn),將所學(xué)的知識融會貫通形帮。之后還有關(guān)于Python高階的學(xué)習(xí)槽惫,比如并發(fā)周叮,異步程序,網(wǎng)絡(luò)編程等等界斜。
GUI實戰(zhàn)
話說Python搞后臺服務(wù)的較多则吟,但是跨平臺的GUI開發(fā)其實也不弱,通過幾個GUI的練習(xí)锄蹂,鞏固一下前面所學(xué)的知識氓仲。
常用的GUI庫
-
Tkinter
tkinter(Tk interface)是Python的標(biāo)準(zhǔn)GUI庫,支持跨
平臺的GUI程序開發(fā)得糜。 -
PyQT
PyQt是一個創(chuàng)建GUI應(yīng)用程序的工具包敬扛。它是Python編程語言和Qt庫的成功融合。Qt庫是目前最強大的庫之一朝抖。在線指南
-
wxPython
wxPython是Python語言的一套優(yōu)秀的GUI圖形庫啥箭,允許Python程序員很方便的創(chuàng)建完整的、功能健全的GUI用戶界面治宣。 wxPython是作為優(yōu)秀的跨平臺GUI庫wxWidgets的Python封裝和Python模塊的方式提供給用戶的急侥。
就如同Python和wxWidgets一樣,wxPython也是一款開源軟件侮邀,并且具有非常優(yōu)秀的跨平臺能力坏怪,能夠支持運行在32 [1] /64位windows、絕大多數(shù)的Unix或類Unix系統(tǒng)绊茧、Macintosh OS X下铝宵。