Python的oop概述
python是面向?qū)ο蟮恼Z(yǔ)言,那么究竟什么是面向?qū)ο?#xff1f;
首先理解類(lèi)
類(lèi):在中文中的定義,許多相同或相似事物的綜合。根據(jù)這個(gè)定義,類(lèi)是許多相同或相似的實(shí)物聚在一起的。譬如,人類(lèi),鳥(niǎo)類(lèi),花類(lèi)等。
面向?qū)ο蟮娜齻€(gè)特征
類(lèi)的單個(gè)具體實(shí)例可以稱(chēng)之為對(duì)象,把類(lèi)具體化單個(gè)實(shí)體的過(guò)程,這個(gè)過(guò)程稱(chēng)為類(lèi)的實(shí)例化!
面向?qū)ο蟪绦蛟O(shè)計(jì)中的術(shù)語(yǔ)對(duì)象基本上可以看做數(shù)據(jù)(特性)以及由一系列可以存取,操作這些數(shù)據(jù)的方法所組成的集合。
面向?qū)ο蟮娜齻€(gè)基本特征:封裝,繼承,多態(tài)。
創(chuàng)建對(duì)象的過(guò)程稱(chēng)之為實(shí)例化,當(dāng)一個(gè)對(duì)象被創(chuàng)建之后,包含三個(gè)方面的特性:對(duì)象的句柄,屬性和方法。對(duì)象的句柄用于區(qū)分不同的對(duì)象,當(dāng)對(duì)象被創(chuàng)建后,該對(duì)象會(huì)獲取一塊存儲(chǔ)空間,存儲(chǔ)空間的地址即為對(duì)象的標(biāo)識(shí)。
- 多態(tài):對(duì)不同的類(lèi)的對(duì)象使用同樣的操作。
- 封裝:對(duì)外部世界隱藏對(duì)象的工作細(xì)節(jié)。
- 繼承:以普通的類(lèi)為基礎(chǔ)類(lèi)建立專(zhuān)門(mén)的類(lèi)對(duì)象。
通過(guò)實(shí)例理解面向?qū)ο蟮囊恍┬g(shù)語(yǔ)和三個(gè)基本特征:
構(gòu)造方法與析構(gòu)函數(shù)
- 構(gòu)造方法:在實(shí)例化時(shí)做的一些初始化工作。
- 析構(gòu)函數(shù):在實(shí)例銷(xiāo)毀時(shí),執(zhí)行的一些操作。
實(shí)例化上面的類(lèi),
>>> a = People("China","hitler",20) #實(shí)例化一個(gè)類(lèi)時(shí),這時(shí)候構(gòu)造函數(shù)會(huì)自動(dòng)執(zhí)行>>> a.get_info() #通過(guò)實(shí)例訪(fǎng)問(wèn)類(lèi)中的實(shí)例方法 -------------------The hitler info-------------------- The hitler comes from China, is 20 old在類(lèi)中定義屬性時(shí),若屬性是以雙下劃線(xiàn)開(kāi)始的則為私有屬性,例如self.__age屬性,而像self.country和self.name屬性則是公有屬性,無(wú)論是私有屬性還是公有屬性,每個(gè)通過(guò)實(shí)例化得到的類(lèi)都有這些屬性。
在實(shí)例化時(shí),我們可以像給函數(shù)傳入?yún)?shù)那樣,給類(lèi)傳入?yún)?shù),而這些參數(shù)的最終被賦值的操作就是在構(gòu)造函數(shù)中執(zhí)行的。構(gòu)造函數(shù)在類(lèi)實(shí)例化的時(shí)候會(huì)自動(dòng)執(zhí)行。
注意私有屬性和實(shí)例屬性的訪(fǎng)問(wèn)方法的不同:
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' >>> a.name #訪(fǎng)問(wèn)實(shí)例屬性 'hitler' >>> a.country #訪(fǎng)問(wèn)實(shí)例屬性 'China' >>> a.__age #方位私有屬性 Traceback (most recent call last):File "<input>", line 1, in <module> AttributeError: 'People' object has no attribute '__age' >>> a._People__age #私有屬性的訪(fǎng)問(wèn)方法,實(shí)例化名._類(lèi)名__私有屬性名 20 >>> del a #刪除一個(gè)實(shí)例,這時(shí)候,析構(gòu)函數(shù)會(huì)自動(dòng)執(zhí)行 hitler has died #析構(gòu)函數(shù):在實(shí)例銷(xiāo)毀的時(shí)候自動(dòng)執(zhí)行的,通常用于做一些收尾的工作,關(guān)閉一些數(shù)據(jù)庫(kù)連接或者關(guān)閉打開(kāi)的臨時(shí)文件。析構(gòu)函數(shù):在實(shí)例銷(xiāo)毀的時(shí)候自動(dòng)執(zhí)行的,通常用于做一些收尾的工作,關(guān)閉一些數(shù)據(jù)庫(kù)連接或者關(guān)閉打開(kāi)的臨時(shí)文件。
在上面的例子中,使用del刪除了實(shí)例a,然后會(huì)自動(dòng)返回析構(gòu)函數(shù)執(zhí)行的結(jié)果。
可以對(duì)實(shí)例進(jìn)行增加,刪除,修改操作:
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' 對(duì)象屬性的增刪改 >>> A = People("USA", "jobs", "53") >>> A.country #可以通過(guò)實(shí)例修改對(duì)應(yīng)的屬性值 'USA' >>> A.country = "UKA" >>> A._People__age = 55 >>> A.get_info() ##可以看到實(shí)例的屬性值已經(jīng)修改 -------------------The jobs info-------------------- The jobs comes from UKA, is 55 old #可以通過(guò)del刪除某個(gè)屬性 >>> del A.country >>> A.get_info() #報(bào)錯(cuò),沒(méi)有對(duì)應(yīng)的country屬性 Traceback (most recent call last):File "<input>", line 1, in <module>File "E:\pycharm\class_method.py", line 14, in get_infoprint("The %s comes from %s, is %d old" % (self.name, self.country, self.__age)) AttributeError: 'People' object has no attribute 'country' -------------------The jobs info-------------------->>> A.country = "China" #添加屬性 >>> A.get_info() #可以看到屬性添加成功 -------------------The jobs info-------------------- The jobs comes from China, is 55 old注意上面的通過(guò)實(shí)例對(duì)屬性的增加,刪除,修改操作僅對(duì)當(dāng)前的實(shí)例有效;而對(duì)于類(lèi)的其余實(shí)例則沒(méi)有效果??梢宰鋈缦聹y(cè)試以證明:
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' >>> a = People("USA","swift",29) #實(shí)例化一個(gè)對(duì)象 >>> a.pos = "singer" #給對(duì)象添加一個(gè)pos屬性 >>> a.pos #對(duì)象a具有pos屬性 'singer'>>> B = People("UKA","king",80) #再實(shí)例化一個(gè)對(duì)象B>>> B.pos Traceback (most recent call last): #對(duì)象B沒(méi)有pos屬性File "<input>", line 1, in <module> AttributeError: 'People' object has no attribute 'pos'>>> a.get_info() -------------------The swift info-------------------- The swift comes from USA, is 29 old >>> b.get_info() -------------------The king info-------------------- The king comes from UKA, is 80 old解釋:
創(chuàng)建類(lèi)的時(shí)候python會(huì)在內(nèi)存中為類(lèi)開(kāi)辟一段內(nèi)存空間,實(shí)例化的時(shí)候,python會(huì)為每一個(gè)實(shí)例開(kāi)辟一段內(nèi)存空間,每個(gè)實(shí)例的內(nèi)存空間都是相互獨(dú)立的,因此更改了a的內(nèi)存空間,并不會(huì)影響B(tài)的內(nèi)存空間。
若想使更改的效果,對(duì)類(lèi)的每一個(gè)實(shí)例都生效,可以使用類(lèi)變量。
在類(lèi)變量之前,先說(shuō)一下self參數(shù)。在類(lèi)中定義的方法,每個(gè)方法都有一個(gè)self參數(shù),那么self參數(shù)該如何理解?
- 在上面的實(shí)例中,通過(guò)類(lèi)實(shí)例化了兩個(gè)對(duì)象a和b,那么這兩個(gè)對(duì)象都有g(shù)et_info()方法,但是在調(diào)用的時(shí)候并沒(méi)有出錯(cuò),我們只能通過(guò)某一個(gè)具體對(duì)象得到這個(gè)對(duì)象的信息,也就是說(shuō)我們只能通過(guò)a的get_info()方法得到對(duì)象a的相關(guān)信息,而不是得到b的信息。這個(gè)的實(shí)現(xiàn)就是因?yàn)閟elf參數(shù)的作用。
- 在實(shí)例化的過(guò)程時(shí),python會(huì)執(zhí)行構(gòu)造函數(shù),做一些初始化的工作,這時(shí)候python會(huì)為這個(gè)實(shí)例開(kāi)辟一段內(nèi)存空間,會(huì)把這個(gè)實(shí)例名(通過(guò)self參數(shù)傳遞)和一些屬性信息一起存入內(nèi)存,這樣調(diào)用的時(shí)候,通過(guò)self參數(shù)來(lái)區(qū)分不同的實(shí)例可以準(zhǔn)確的調(diào)用到對(duì)應(yīng)的屬性信息。
類(lèi)變量:
首先滿(mǎn)足上面提到的,讓更改對(duì)每一個(gè)實(shí)例都生效。
class People(object):addr = "Earth" # 類(lèi)變量def __init__(self, country, name, age=23):self.country = countryself.name = nameself.__age = age然后對(duì)上面的類(lèi)進(jìn)行實(shí)例化操作,如下:
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' >>> a = People("USA","swift", 29) #實(shí)例化兩個(gè)類(lèi) >>> b = People("China","wxz", 24) >>> a.addr #這兩個(gè)類(lèi)都有一個(gè)addr屬性,注意addr類(lèi)變量在類(lèi)中定義的方法 'Earth' >>> b.addr 'Earth'>>> a.addr = "Moon" #注意這樣做只是在實(shí)例a中添加了實(shí)例屬性addr,而不是修改類(lèi)變量addr。 >>> a.addr #實(shí)例a訪(fǎng)問(wèn)的是實(shí)例屬性中的addr。 'Moon' >>> b.addr #而實(shí)例b訪(fǎng)問(wèn)的是類(lèi)變量addr。因此結(jié)果不同 'Earth' >>> People.addr = "Moon" #修改類(lèi)變量,這時(shí)候?qū)嵗齛仍然訪(fǎng)問(wèn)的是實(shí)例屬性addr,而實(shí)例b訪(fǎng)問(wèn)的是類(lèi)變量addr。 >>> a.addr 'Moon' >>> b.addr 'Moon' #再實(shí)例化一個(gè)實(shí)例對(duì)象c,可以發(fā)現(xiàn)c的addr屬性已經(jīng)是修改之后的屬性。 >>> c = People("UKA", "King",88) >>> c.addr #實(shí)例對(duì)象c訪(fǎng)問(wèn)的是類(lèi)變量addr。 'Moon'在上面的實(shí)例中,我們給實(shí)例a添加一個(gè)實(shí)例屬性addr,而這時(shí)候類(lèi)變量也有一個(gè)屬性addr,那么在訪(fǎng)問(wèn)的時(shí)候?qū)嵗龝?huì)怎么去調(diào)用對(duì)應(yīng)的值呢?
通過(guò)以上的例子可以得出如下結(jié)論:屬性查找,首先查找實(shí)例本身是否有對(duì)應(yīng)的屬性,若找到則返回結(jié)果,停止查找;否則就繼續(xù)查找類(lèi)中的屬性變量。
在這里實(shí)例a因?yàn)樘砑恿薬dd實(shí)例r屬性,因此實(shí)例a只會(huì)返回實(shí)例本身的addr結(jié)果;而實(shí)例b和實(shí)例c,因?yàn)楸旧淼臎](méi)有addr實(shí)例屬性(構(gòu)造函數(shù)中沒(méi)有定義),因此會(huì)返回類(lèi)變量addr的值。
類(lèi)變量是類(lèi)的各個(gè)實(shí)例共有的屬性。當(dāng)然這個(gè)屬性也可以放在構(gòu)造函數(shù)中,在每個(gè)實(shí)例初始化的時(shí)候,就會(huì)自動(dòng)生成這個(gè)屬性。
但是上面提到過(guò)python會(huì)為每個(gè)實(shí)例開(kāi)辟一個(gè)內(nèi)存空間,因此當(dāng)實(shí)例非常巨大的時(shí)候,這樣做會(huì)占用存儲(chǔ)空間。采用類(lèi)變量的形式更節(jié)省空間。
封裝:
在這個(gè)實(shí)例中有一個(gè)簡(jiǎn)單的方法就是get_info()。對(duì)于一個(gè)對(duì)象也就是實(shí)例來(lái)說(shuō),要想得到這個(gè)對(duì)象的具體信息,只需要調(diào)用get_info()這個(gè)方法即可,然后就會(huì)返回對(duì)象的具體信息。但是具體是怎么樣得到這些信息的,這個(gè)實(shí)例是不知道的。這種形式就是封裝。把一些功能實(shí)現(xiàn)的細(xì)節(jié)不對(duì)外暴露,隱藏起來(lái)就是封裝。
經(jīng)典類(lèi)與新式類(lèi):
- python2中默認(rèn)創(chuàng)建的都是經(jīng)典類(lèi),但創(chuàng)建類(lèi)時(shí)使用object參數(shù)時(shí),就是新式類(lèi)。
- python3中創(chuàng)建的類(lèi)都是新式類(lèi),但習(xí)慣上使用object參數(shù)。
- 經(jīng)典類(lèi)與新式類(lèi)的區(qū)別在多種繼承中可以用到
繼承:
- 繼承就是一個(gè)類(lèi)繼承了另一個(gè)類(lèi),繼承的新類(lèi)擁有父類(lèi)屬性和方法,實(shí)現(xiàn)代碼的重復(fù)使用和代碼的擴(kuò)展。
- 再繼承時(shí),可以對(duì)父類(lèi)的一些屬性和方法進(jìn)行重寫(xiě)。
- 需要特別注意的是構(gòu)造方法的重寫(xiě)。
上面定義了一個(gè)父類(lèi)People,兩個(gè)子類(lèi)teacher和student,都繼承了people。
實(shí)例化操作:
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' a = People("wxz") b = Teacher(name="steve", pos="teacher", school="Peking university") d = Student(name="job", pos="Stuent", score=88, course=("數(shù)學(xué)","語(yǔ)文","物理"))In [6]: a.get_info() My name is wxz, I have not a workIn [7]: b.get_info() My name is steve, I am a teacher The colleage is Peking universityIn [8]: d.get_info() My name is job, I am a Stuent My score is 88 I have learned the 數(shù)學(xué) 語(yǔ)文 物理實(shí)例化的每一個(gè)對(duì)象都可以調(diào)用get_info()方法,得到其對(duì)應(yīng)的信息。這三個(gè)對(duì)象是不一樣的,分別為people, teacher,student對(duì)象。
若有一個(gè)函數(shù),只要傳入對(duì)應(yīng)的對(duì)象,然后就可以調(diào)用函數(shù)得到對(duì)應(yīng)的信息。如下這種形式:
在這個(gè)例子中,并不知道a,b,d是什么樣的對(duì)象,要做的只是把這三個(gè)對(duì)象傳入了print_intfo函數(shù),然后函數(shù)會(huì)自動(dòng)返回對(duì)應(yīng)的對(duì)象信息。
這里只有一個(gè)print_info的接口,但是不同的對(duì)象都可以調(diào)用這個(gè)接口,這種行為就叫做多態(tài)。
多態(tài)就是一種接口的多種使用。
下面一個(gè)簡(jiǎn)單的多態(tài)實(shí)例
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' list1 Out[22]: ['a', 'f', 'd', 's', 'f', 'a', 's', 'd', 'f'] #列表tuple1 Out[23]: ('f', 'g', 'a', 'g', 'f', 'd', 'g', 'd', 'f') #元組len(list1) Out[24]: 9len(tuple1) Out[25]: 9對(duì)于len()函數(shù)來(lái)說(shuō)并不知道list1是列表,tuple1是元組,len()函數(shù)只是接受一個(gè)參數(shù)對(duì)象,然后返回這個(gè)參數(shù)對(duì)象的長(zhǎng)度。也可以理解為多態(tài)的一種使用。
面向?qū)ο蟮娜齻€(gè)基本特征:封裝,繼承,多態(tài)。
面向的對(duì)象的屬性:
-
靜態(tài)屬性
-
私有屬性
-
? 實(shí)例屬性
-
? 類(lèi)屬性(類(lèi)變量)
-
-
動(dòng)態(tài)屬性(就是方法)
- 實(shí)例方法
- ? 私有方法–和私有屬性一樣是雙下劃線(xiàn)開(kāi)始的,調(diào)用形式和私有屬性一樣,只能通過(guò)類(lèi)中的方法調(diào)用
總結(jié)
以上是生活随笔為你收集整理的Python的oop概述的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python uuid 介绍
- 下一篇: Python构造栈结构