對於非程序員科班出身的技術人員,理解很多開發思想領域裏面的事情,其實是一件挺痛苦的事情,直到接觸到了Python當中的類,我才明白了什麼是面向對象,更多的理解還是要通過實際的代碼操練才能夠慢慢的掌握。
今天記錄一下什麼是面向對象,在Python的編程世界裏爲什麼要用到類。
一、面向對象
將大家共有的特性剝離出來進行抽象的過程就是面向對象,這是我對面向對象最直觀的理解,例如我們在工廠生產汽車,每一款車都有自己的生產平臺,試想一下這樣的場景,A款車有100個工人在獨立生產,其中20個人生產底盤,20個人研發發動機,40個人製作車架、車門,20個人負責最終的車輛組裝,B款車同樣有100個人幹着和A款車相同的事情,如果世界是這個樣子,豐田、大衆也早就倒閉了,不管是任何車型,雖然每款車都有自己獨立的生產平臺,但是很多東西一定是具備相同屬性的,例如發動機、方向盤、車座、輪胎,在小到螺絲帽等等,我們可以將這些共有的東西完全獨立出來,變成每款車型的共有屬性,那麼100個工人可能有50個人都是負責公共部分的,節省了人力成本的同時,也節省了資源成本,例如我們要對座椅的尺寸進行調整,那麼僅需要對這50個人的工作內容進行調整即可,而不需要對每款車進行獨立的操作,這就是面向對象爲我們帶來的好處。
二、Python中的面向對象——類
簡單的舉例了面向對象的生產場景,我們再通過Python中函數式編程和類編程來對比各自的特點。
例如有一個簡單的需求,就是開發一個郵件客戶端程序,可以通過程序,自定義的發送我們想要發送的內容。
1、函數式編程
# 僞代碼 def send_mail(to_user, title, content): smtp_host = "mail.test1.com" smtp_username = "test_user1" smtp_password = "test_password1" smtp_obj = smtplib.SMTP(smtp_host, smtp_username, smtp_password) smtp_obj.sendmail(to_user, title, content) send_mail("[email protected]", "test_mail", "test_content")
我們通過上述僞代碼簡單實現了郵件發送的需求,但如果想讓更多的人來使用使用這個功能,就會遇到一些問題,例如大家的smtp、用戶口令都不一樣,我們就要改造代碼變成下面的樣子。
# 僞代碼 def send_mail(smtp_host, smtp_username, smtp_password, to_user, title, content): smtp_obj = smtplib.SMTP(smtp_host, smtp_username, smtp_password) smtp_obj.sendmail(to_user, title, content) send_mail("mail.test1.com", "test_user1", "test_password1", "[email protected]", "test_mail", "test_content") send_mail("mail.test2.com", "test_user2", "test_password2", "[email protected]", "test_mail", "test_content") send_mail("mail.test3.com", "test_user3", "test_password3", "[email protected]", "test_mail", "test_content")
我們又通過上述方式實現了多人發送的功能,程序寫到這裏看起來貌似還沒什麼問題,但如果此時我們的程序需求又增加了,例如不只是發郵件了,同時要有接收、刪除、等等功能,我們的代碼又變成下面的樣子。
# 僞代碼 def send_mail(smtp_host, smtp_username, smtp_password, to_user, title, content): smtp_obj = smtplib.SMTP(smtp_host, smtp_username, smtp_password) smtp_obj.sendmail(to_user, title, content) def recv_mail(smtp_host, smtp_username, smtp_password) smtp_obj = smtplib.SMTP(smtp_host, smtp_username, smtp_password) # mail 接收代碼 ... def delete_mail(smtp_host, smtp_username, smtp_password) smtp_obj = smtplib.SMTP(smtp_host, smtp_username, smtp_password) # mail 刪除功能 ... send_mail("mail.test1.com", "test_user1", "test_password1", "[email protected]", "test_mail", "test_content") recv_mail("mail.test1.com", "test_user1", "test_password1", recv_argv, ...) delete_mail("mail.test1.com", "test_user1", "test_password1", delete_argv, ...)
我們看僅一個用戶想要實現三個功能時,就需要寫這麼多代碼,此時代碼顯的就有些累贅了,更致命的是如果smtp的地址變了,我要把每個功能函數的傳遞參數都要改一遍,這顯然增加了工作成本和錯誤出現的機率,但我們發現每一項功能都有幾個共同的屬性,就是smtp地址,smtp用戶,smtp密碼,我們完全可以將這三個屬性進行獨立,通過類的封裝特性來實現,即下面的面向對象式編程。
2、面向對象式編程
Python當中通過創建類,就可以很好的實現面向對象的編程思想,同樣是上面郵件發送程序,我們來用類的方式實現。
# 僞代碼 class MailTools: def __init__(self, smtp_host, smtp_username, smtp_password): self.smtp_host = smtp_host self.smtp_username = smtp_username self.smtp_password = smtp_password self.smtp_obj = smtplib.SMTP(smtp_host, smtp_username, smtp_password) # 發送郵件 def send_mail(self, to_user, title, content): self.smtp_obj.sendmail(to_user, title, content) # 接收郵件 def recv_mail(self, recv_argv, ...) # mail 接收代碼 # 刪除郵件 def delete_mail(self, delete_argv, ...) # mail 刪除代碼 test_mail = MailTools("mail.test1.com", "test_user1", "test_password1") test_mail.send_mail(...) test_mail.recv_mail(...) test_mail.delete_mail(...)
我們通過上述類代碼的方式,創建了對象test_mail,然後調用它下面的send_mail、recv_mail方法等,這樣的方式使得我們的代碼邏輯更加清晰,如果smtp參數發生改變時,我們也僅需要修改對象實例化時的參數即可。
在實現簡單功能時我們使用函數式編程,因爲它足夠簡單、快速,但隨着程序功能的不斷升級、提供多個複雜邏輯操作時,函數式變成就顯的不那麼好用了,因此針對不同的代碼場景,我們要用好Python中的編程方式。
Python中類的知識點:
1、"__init__" 方法爲Python中的構造方法,用於初始化我們的類,也就是初始化我們希望的共有屬性,同時構造方法中可以執行該類中其他的函數。
2、self是一個形式參數,爲該類的實例化對象,例如 a = My_Class() 中,可以理解a就是self參數。
3、創建對象時,類的後面需要加括號,即完成類的實例化,同時Python會自動查找該類中的構造方法。
4、類中如果定義了多個功能函數,那麼這些函數可以稱之爲該類實例化對象所擁有的方法。
5、面向對象式編程的三大特性:封裝、繼承、多態