Python面向對象編程基礎解析(二)
Python最近挺火呀,比鹿晗薛之謙還要火,當然是在程序員之間。下面我們看看有關Python的相關內容。
上一篇文章我們已經介紹了部分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已經被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-09
python3+PyQt5 自定義窗口部件--使用窗口部件樣式表的方法
今天小編就為大家分享一篇python3+PyQt5 自定義窗口部件--使用窗口部件樣式表的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-06-06

