您好,登錄后才能下訂單哦!
這篇文章主要講解了“Python對(duì)象是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Python對(duì)象是什么”吧!
類和對(duì)象的概念
類是對(duì)我們要處理的客觀事物的抽象。類用來描述具有相同的屬性和方法的對(duì)象的集合,它定義了該集合中每個(gè)對(duì)象所共有的屬性和方法。對(duì)象是類在內(nèi)存的實(shí)例,一個(gè)類可以實(shí)例化為多個(gè)對(duì)象。類是抽象的,不占用內(nèi)存,而對(duì)象是具體的,占用存儲(chǔ)空間。
類的成員
作為Python初學(xué)者,大可不必把精力花費(fèi)在令人費(fèi)解的概念上,只需要掌握使用類的基本要素就可以了。未來的日子里,你有足夠多的時(shí)間慢慢體會(huì)OOP的博大精深。隨著經(jīng)驗(yàn)的積累,OOP會(huì)自然而然地成為你的思維工具。
下面的代碼,定義了一個(gè)名為A的類。所有的類,都有構(gòu)造函數(shù)和析構(gòu)函數(shù),此外,還可以包含成員函數(shù)和成員變量。我喜歡把成員函數(shù)叫做類的方法,把成員變量叫做類的屬性。
當(dāng)類被實(shí)例化為對(duì)象時(shí),首先執(zhí)行構(gòu)造函數(shù),當(dāng)對(duì)象被銷毀時(shí),會(huì)自動(dòng)執(zhí)行析構(gòu)函數(shù)。一般的,我們會(huì)在構(gòu)造函數(shù)中進(jìn)行初始化工作,在析構(gòu)函數(shù)中進(jìn)行清理工作。
讀到這里,有很多初學(xué)者一定會(huì)說:我定義類的時(shí)候,寫過構(gòu)造函數(shù),但從沒有寫過析構(gòu)函數(shù),你為什么說所有的類都有構(gòu)造函數(shù)和析構(gòu)函數(shù)呢?沒錯(cuò),定義類的時(shí)候,即便我們不寫構(gòu)造函數(shù)和析構(gòu)函數(shù),這兩個(gè)方法也照樣存在(析構(gòu)函數(shù)稍微有點(diǎn)特殊,我們不能直接看到它——除非是我們自己定義的)。如果我們自己定義了構(gòu)造函數(shù)和析構(gòu)函數(shù),則將會(huì)取代系統(tǒng)自動(dòng)賦予的這兩個(gè)函數(shù)。下面的例子清晰地說明了其中的奧秘:類A既沒有構(gòu)造函數(shù),也沒有析構(gòu)函數(shù),類B只有析構(gòu)函數(shù),兩個(gè)類都可以生成類實(shí)例,也都可以銷毀,且 del b 時(shí)首先調(diào)用了自定義的析構(gòu)函數(shù)。
新式類和舊式類
在PY2中,類有新式類和舊式類兩種。新式類需要繼承自虛類Object,舊式類則不需要。PY2中類的寫法有三種:
在PY3中,只有新式類,不再支持舊式類。你如果習(xí)慣繼承Object的寫法,也完全沒有問題。上面三種寫法在PY3中都被解釋成新式類。新式類和舊式類的主要區(qū)別是:
新式類可以繼承Object的構(gòu)造函數(shù)和析構(gòu)函數(shù),如果類的構(gòu)造和析構(gòu)函數(shù)沒有特別的工作,可以省略。而舊式類則不能:
此時(shí)用PY2運(yùn)行,會(huì)出現(xiàn)錯(cuò)誤:AttributeError: class A has no attribute '__init__',使用PY3不會(huì)出現(xiàn)此錯(cuò)誤。若改成新式類寫法:
仍然用PY2運(yùn)行,則都不會(huì)出錯(cuò)。
新式類可以使用super:
多重繼承時(shí),各父類的初始化和函數(shù)查找順序不同:舊式類為深度優(yōu)先繼承,新式類為廣度優(yōu)先繼承。
靜態(tài)變量和實(shí)例變量
在構(gòu)造函數(shù)中定義的變量,我們稱之為實(shí)例變量。實(shí)例變量只能在實(shí)例化后使用<對(duì)象名.變量名>的方式訪問。靜態(tài)變量一般定義在類的開始位置,獨(dú)立于構(gòu)造函數(shù)之外。靜態(tài)變量既可以<對(duì)象名.變量名>的方式訪問,也可以<類名.變量名>的方式訪問。通常,類的靜態(tài)變量一般用于保存類的靜態(tài)屬性,該屬性可被類的方法使用,但不應(yīng)該被類的方法修改。
靜態(tài)函數(shù)
與其他語音的靜態(tài)函數(shù)不同,Python的靜態(tài)函數(shù)有兩種,都是用裝飾器實(shí)現(xiàn)的:
Staticmethod 函數(shù)不能使用Self參數(shù),因此不成訪問任何成員變量,只能通過類名訪問類的靜態(tài)變量。
Classmethod 函數(shù)也不能使用Self參數(shù),因此不成訪問任何成員變量,但它有cls參數(shù)。cls參數(shù)不是對(duì)象的引用,而是類的引用,可以通過cls參數(shù)訪問類的靜態(tài)變量。
面向?qū)ο笕?/p>
面向?qū)ο螅腥笠兀豪^承、封裝、多態(tài)。這里面概念非常多,往往越講越糊涂。為了不至于誤導(dǎo)讀者,我盡可能不做解釋,只給出例子,請(qǐng)自行揣摩。
(1) 繼承
如果派生類只有一個(gè)父類,就是單繼承。這是最常見的類定義形式。
如果派生類有多個(gè)父類,就是多繼承。
不管是單繼承還是多繼承,都可以在派生類中重寫父類的函數(shù)——這叫做覆蓋。
(2) 封裝
所謂封裝,就是將類的成員變量、成員函數(shù)整合在一起,并對(duì)關(guān)鍵的信息進(jìn)行保護(hù)或隱藏。信息保護(hù)或隱藏有三個(gè)級(jí)別:公有、保護(hù)、私有。如果你有C++的使用經(jīng)驗(yàn),我們先來回顧一下C++的信息隱藏規(guī)則:
公有成員:對(duì)類外部的任何代碼可見;
保護(hù)成員:對(duì)類外部的任何代碼都不可見,但對(duì)派生類可見;
私有成員:對(duì)類外部及派生類都不可見。
對(duì)應(yīng)這三個(gè)級(jí)別,Python 是這樣定義的:
以英文字母開頭的成員為公有成員
以一個(gè)下劃線開頭的成員為保護(hù)成員
以兩個(gè)下劃線開關(guān)的成員為私有成員
下面我們?cè)囋?Python 的信息保護(hù)或隱藏規(guī)則是否有效。
試試訪問公有成員:
公有成員訪問規(guī)則與C++相同。先跳過保護(hù)成員,看看私有成員:
私有成員的訪問規(guī)則也與C++相同。那我為什么跳過保護(hù)成員了?來試試吧:
看到這里就已經(jīng)不對(duì)了,應(yīng)該只有類內(nèi)部的代碼和派生類能使用啊,怎么可以直接用了呢?是的,Python的保護(hù)成員訪問規(guī)則與C++的確實(shí)不一樣。那 Python 的保護(hù)成員是什么樣的機(jī)制呢?原來,在 Python 的OOP中,保護(hù)成員公有成員沒有任何區(qū)別。保護(hù)規(guī)則僅適用于 from xxx import * 這一種情況。
testA.py
class A(object): pass class _B(object): pass
testB.py
from testA import * a = A() b = _B()
執(zhí)行testB.py時(shí):
Traceback (most recent call last): File "testB.py", line 4, inb = _B()NameError: name '_B' is not defined
此時(shí),保護(hù)成員_B被保護(hù)了。但這種情況僅適用于from xxx import *這一種情況。如果testB.py這樣寫:
testB.py
from testA import A, _B a = A() b = _B()
或者:
import testA a = testA.A() b = testA._B()
則是沒有任何問題的。
(3) 多態(tài)
當(dāng)父類有多個(gè)派生類,且派生類都實(shí)現(xiàn)了同一個(gè)成員函數(shù),則可以實(shí)現(xiàn)多態(tài):
class H2O(object): def what(self): print("I am H2O") class Water(H2O): def what(self): print("I am water") class Ice(H2O): def what(self): print("I am ice") class WaterVapor(H2O): def what(self): print("I am water vapor"); def what(obj): obj.what() objs = [H2O(), Water(), Ice(), WaterVapor()] for obj in objs: what(obj)
抽象類
抽象類不能被實(shí)例化,只能作為父類被其它類繼承,且派生類必須實(shí)現(xiàn)抽象類中所有的成員函數(shù)。抽象類應(yīng)用場(chǎng)景是什么呢?我曾經(jīng)做過很多下載數(shù)據(jù)的腳本插件,不同的數(shù)據(jù)源使用不同的腳本,所有這些腳本要求必須有名字相同的方法,此時(shí),抽象類就派上用場(chǎng)了。
單例模式
單例模式(Singleton Pattern)是一種常用的軟件設(shè)計(jì)模式,該模式的主要目的是確保某一個(gè)類只有一個(gè)實(shí)例存在。當(dāng)你希望在整個(gè)系統(tǒng)中,某個(gè)類只能出現(xiàn)一個(gè)實(shí)例時(shí)(如軟件配置類,無論在軟件的什么地方實(shí)例化,永遠(yuǎn)都是那一個(gè)對(duì)象),單例模式就能派上用場(chǎng)。比如,Python 日志模塊中的日志對(duì)象,或者異步通訊框架Twisted 里面的反應(yīng)堆(reactor),都是典型的單例模式——盡管它們不一定是下面這種方法實(shí)現(xiàn)的。
Python可以使用裝飾器的方法使用單例模式:
>>> import abc>>> class A(object, metaclass=abc.ABCMeta): @abc.abstractmethod def a(self): pass @abc.abstractmethod def b(self): pass>>> class C(A): def a(self): print("a")>>> c = C()Traceback (most recent call last): File "", line 1, inc = C()TypeError: Can't instantiate abstract class C with abstract methods b
感謝各位的閱讀,以上就是“Python對(duì)象是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)Python對(duì)象是什么這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。