Python面向對象編程基礎解析(二)
Python最近挺火呀,比鹿晗薛之謙還要火,當然是在程序員之間。下面我們看看有關Python的相關內容。
上一篇文章我們已經(jīng)介紹了部分Python面向對象編程基礎的知識,大家可以參閱:Python面向對象編程基礎解析(一),接下來,我們看看另一篇。
封裝
1.為什么要封裝?
封裝就是要把數(shù)據(jù)屬性和方法的具體實現(xiàn)細節(jié)隱藏起來,只提供一個接口。封裝可以不用關心對象是如何構建的,其實在面向對象中,封裝其實是最考驗水平的
2.封裝包括數(shù)據(jù)的封裝和函數(shù)的封裝,數(shù)據(jù)的封裝是為了保護隱私,函數(shù)的封裝是為了隔離復雜度
3.數(shù)據(jù)的封裝就是在屬性前面加一個__
class People: def __init__(self,name,age,salary): self.name=name self.age=age self.__salary=salary p=People('zhang',19,100000) print(p.name)#zhang print(p.age)#19 print(p.__salary)#AttributeError: 'People' object has no attribute '__salary'
咦,報錯了,讓我們打開對象的名稱空間,看看發(fā)生了什么
print(p.__dict__)#{'name': 'zhang', 'age': 19, '_People__salary': 100000}
哦,原來python把__salary變形成了_People__salary,再來一遍
print(p._People__salary)#100000
所以,Python中并沒有絕對的隱藏,只要你知道了上面這個,就無所謂隱藏了
這些變形操作,只在類的定義階段或者對象定義(實例化階段)階段發(fā)生
雖然在外部無法直接訪問加了__的屬性,但是在類內部可以訪問到,可以這么理解,在定義階段,只要遇到__開頭的,Python解釋器自動識別為_類名__屬性,所以在類內部是可以訪問到的,這樣的話,我們就可以搞一點小事情了
先來看這個
class A: def foo(self): print('from A foo') self.bar() def bar(self): print('from A bar') class B(A): def bar(self): print('from B bar') b=B() b.foo() #from A foo #from B bar 別想多了,調用函數(shù)時別看定義位置,要看調用位置
如果就是想調用父類的bar()函數(shù)呢?該怎么做
class A: def foo(self): print('from A foo') self.__bar() def __bar(self): print('from A bar') class B(A): def __bar(self): print('from B bar') b=B() b.foo() #from A foo #from A bar 有沒有感受到編程的美妙
4.封裝的應用
1)不讓外界看到我們的數(shù)據(jù)屬性是怎么定義的,只能通過我們提供的接口,看到我們允許外界看到的內容
class People: def __init__(self,name,age,height,weight,hobby): self.__name=name self.__age=age self.__height=height self.__weight=weight self._hobby=hobby def tell_info(self): print(''' name:%s age:%s height:%s weeight:%s '''%(self.__name,self.__age, self.__height,self.__weight)) p=People('zhang',18,1.90,75,'read') p.tell_info()
2)更常用的場景是,我們可以限制數(shù)據(jù)的類型,添加自己的邏輯以后再封裝好給用戶
def tell_name(self): print(self.__name) #修改名字 def set_name(self,new): if not isinstance(new,str): raise TypeError('名字必須是字符串類型') self.__name=new
5.看我們上面的操作,用戶查看名字的時候還得p.tell_name(),本來是個數(shù)據(jù)屬性,卻被我們搞得變成了一個函數(shù),怎么偽裝一下呢,就可以用到property這個裝飾器了
class People: def __init__(self,name,age,height,weight,hobby): self.__name=name self.__age=age self.__height=height self.__weight=weight self._hobby=hobby @property def name(self): return self.__name p=People('zhang',18,1.90,75,'read') print(p.name)#zhang
數(shù)據(jù)屬性還應該有修改,刪除操作
@property def name(self): return self.__name #name已經(jīng)被property修飾過,就有setter和deleter @name.setter def name(self,new): if not isinstance(new,str): raise TypeError('名字必須是字符串類型') self.__name=new @name.deleter def name(self): del self.__name p = People('zhang', 18, 1.90, 75, 'read') print(p.name)#zhang p.name='can' #修改 print(p.name)#can del p.name #刪除 print(p.name)#AttributeError: 'People' object has no attribute '_People__name'
1.多態(tài)
多態(tài)的概念雖然現(xiàn)在才說,但是我們一直在用。多態(tài)就是多種形態(tài)的意思,動物都貓,狗,豬等等,這些都是動物的多種形態(tài)。
反映在Python中,多態(tài)就意味著就算不知道變量所引用的對象類型是什么,也能對它進行操作。比如序列類型有計算長度的方法len(),那我們拿到一個序列類型x,我們不需要知道x是什么類型,只需要知道它是序列類型,那我們就可以用len(x)的方法計算x的長度。這就是多態(tài)性,Python本身就是多態(tài)的
當然我們學過一個內置函數(shù)isinstance(),可以用它來判斷數(shù)據(jù)類型,但是這可不符合多態(tài)優(yōu)美的特性
2.綁定方法與非綁定方法
類里面定義的函數(shù)有兩種,綁定方法和非綁定方法
1)綁定方法
綁定方法又分為綁定給類的方法和綁定給對象用的方法。
凡是定義在類中,且沒有被任何裝飾器修飾的方法,都是綁定給對象用的方法。
特點是obj.func()會自動把obj當作第一個參數(shù)傳入,因為func的邏輯就是要處理obj
在類中定義的被classmethod裝飾器修飾的方法,就是綁定給類的方法
特點是cls.func()會自動把類cls當作第一個參數(shù)傳入,因為func的邏輯是處理cls,就算是對象調用這個函數(shù),也是把類當成第一個參數(shù)傳入
class People: def __init__(self,name): self.name=name def bar(self): print('----->',self.name) @classmethod def func(cls): print(cls) p1=People('zhang') p1.func() #<class '__main__.People'> People.func()#<class '__main__.People'>
2)非綁定方法
還有一種方法是既不綁定給類,也不綁定給對象的,叫做非綁定方法
用staticmethod裝飾器裝飾
#文件名:pickle_test import hashlib import time import pickle import os student_path=r'C:\Users\Administrator\PycharmProjects\test\student' class People: def __init__(self,name,sex,user_id): self.name=name self.sex=sex self.user_id=user_id self.id = self.create_id() def tell_info(self): print(''' --------%s info-------- id:%s name:%s sex:%s user_id:%s ''' %(self.name,self.id,self.name,self.sex,self.user_id)) def create_id(self): m=hashlib.md5() m.update(self.name.encode('utf-8')) m.update(self.sex.encode('utf-8')) m.update(str(self.user_id).encode('utf-8')) return m.hexdigest() def save(self): with open(self.id,'wb') as f: pickle.dump(self,f) @staticmethod #非綁定方法,就是一個函數(shù),就是一個工具而已,不需要類,也不需對象 def get_all(): res = os.listdir(student_path) for item in res: file_path=r'%s\%s' %(student_path,item) with open(file_path,'rb') as f: obj=pickle.load(f) obj.tell_info() #反序列化.py from pickle_test import People p=People('zhang','male',123123123) p.get_all()
3.軟件開發(fā)規(guī)范
在真正的軟件開發(fā)過程中,并不是把所有代碼寫在一個文件中的,可以想象一下,一個小程序大概有10000行代碼,都寫在一個文件中的話,你還干這行嗎?
正確的方式應該是把程序拆成一個一個模塊。比如常用的bin目錄放可執(zhí)行文件,conf目錄放配置文件
db目錄放數(shù)據(jù),log目錄放日志文件,lib目錄放庫,src目錄放一些重要的代碼,比如重要的邏輯,類的定義等
總結
以上就是本文關于Python面向對象編程基礎解析的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:Python探索之ModelForm代碼詳解、python中requests爬去網(wǎng)頁內容出現(xiàn)亂碼問題解決方法介紹等,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
相關文章
Python3 tkinter 實現(xiàn)文件讀取及保存功能
tkinter是一個跨平臺的GUI庫,開發(fā)的程序可以在win,linux或者mac下運行,tkinter是python自帶的GUI庫,是對圖形庫TK的封裝。本文通過實例代碼給大家介紹Python3 tkinter 實現(xiàn)文件讀取及保存功能,感興趣的朋友跟隨小編一起看看吧2019-09-09python3+PyQt5 自定義窗口部件--使用窗口部件樣式表的方法
今天小編就為大家分享一篇python3+PyQt5 自定義窗口部件--使用窗口部件樣式表的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-06-06