您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“python類的相關(guān)概念”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
什么是類,對象,實(shí)例,類## 標(biāo)題變量(類屬性),實(shí)例變量(實(shí)例屬性)
類變量和類屬性的分類
類調(diào)用實(shí)例方法
類的封裝(enclosure),繼承和多態(tài)
迭代,迭代器(iterator),可迭代對象(iterable object),生成器(generator)
面向?qū)ο缶幊?/strong>(Object-oriented Programming,簡稱 OOP),是一種封裝代碼的方法。比如說,將亂七八糟的數(shù)據(jù)扔進(jìn)列表中,這就是一種簡單的封裝,是數(shù)據(jù)層面的封裝;把常用的代碼塊打包成一個函數(shù),這也是一種封裝,是語句層面的封裝。面向?qū)ο缶幊蹋彩且环N封裝的思想,把描述特征的數(shù)據(jù)和代碼塊(函數(shù))封裝到一起。
面向?qū)ο笾?,常用術(shù)語包括類,對象,屬性,方法:
類:可以理解是一個模板,通過它可以創(chuàng)建出無數(shù)個具體實(shí)例(又稱對象)。
對象(實(shí)例):類并不能直接使用,通過類創(chuàng)建出的實(shí)例才能使用。
屬性:類中的所有變量稱為屬性。
方法:類中的所有函數(shù)通常稱為方法。不過,和函數(shù)所有不同的是,類方法至少要包含一個 self 參數(shù)。類方法無法單獨(dú)使用,只能和類的對象一起使用。
無論是類屬性還是類方法,都無法像普通變量或者函數(shù)那樣,在類的外部直接使用它們。我們可以將類看做一個獨(dú)立的空間,則類屬性其實(shí)就是在類體中定義的變量,類方法是在類體中定義的函數(shù)。
在類體中,根據(jù)變量定義的位置不同,以及定義的方式不同,類屬性又可細(xì)分為以下 3 種類型:
類體中、所有函數(shù)之外:此范圍定義的變量,稱為類屬性或類變量;
類體中,所有函數(shù)內(nèi)部:以“self.變量名”的方式定義的變量,稱為實(shí)例屬性或?qū)嵗兞浚?br/>類體中,所有函數(shù)內(nèi)部:以“變量名=變量值”的方式定義的變量,稱為局部變量。
和類屬性一樣,類方法也可以進(jìn)行更細(xì)致的劃分,具體可分為類方法、實(shí)例方法和靜態(tài)方法。在實(shí)際編程中,幾乎不會用到類方法和靜態(tài)方法,因?yàn)槲覀兺耆梢允褂煤瘮?shù)代替它們實(shí)現(xiàn)想要的功能,但在一些特殊的場景中(例如工廠模式中),使用類方法和靜態(tài)方法也是很不錯的選擇。
和類屬性的分類不同:
類方法:采用 @classmethod 修飾的方法
靜態(tài)方法:采用 @staticmethod> 修飾的方法
實(shí)例方法:不用任何修改的方法
構(gòu)造方法:在創(chuàng)建類時,我們可以手動添加一個 init() 方法,該方法是一個特殊的類實(shí)例方法,稱為構(gòu)造方法(或構(gòu)造函數(shù))。構(gòu)造方法用于創(chuàng)建對象時使用,每當(dāng)創(chuàng)建一個類的實(shí)例對象時,Python 解釋器都會自動調(diào)用它。
實(shí)例方法的調(diào)用方式其實(shí)有 2 種,既可以采用類對象調(diào)用,也可以直接通過類名調(diào)用。
class CLanguage : # 下面定義了2個類變量 name = "python語言" add = "http://c.biancheng.net.python" # __init__是構(gòu)造方法,也屬于實(shí)例方法 def __init__(self,name,add): #下面定義 2 個實(shí)例變量 self.name = name self.add = add print(name,"網(wǎng)址為:",add) # 下面定義了一個say實(shí)例方法 def say(self, content): print(content) #下面定義了一個count實(shí)例方法 def count(self,money): #下面定義了一個局部變量sale sale = 0.8*money print("優(yōu)惠后的價格為:",sale) #下面定義了一個類方法 @classmethod def info(cls): print("正在調(diào)用類方法",cls) #下面定義了一個靜態(tài)方法 @staticmethod def info(name,add): print(name,add) # 將該CLanguage對象賦給clanguage變量 # 通過類名直接調(diào)用實(shí)例方法 # CLanguage.say("通過類名直接調(diào)用實(shí)例方法")會報錯,必須手動將 clang 這個類對象傳給self 參數(shù) clang = CLanguage("C語言中文網(wǎng)1","http://c.biancheng.net")#傳入的參數(shù)要和init的一樣 CLanguage.say(clang, "通過類名直接調(diào)用實(shí)例方法") # 通過類對象直接調(diào)用實(shí)例方法 clang2 = CLanguage("C語言中文網(wǎng)2","http://c.biancheng.net") clang2.say("通過類對象直接調(diào)用實(shí)例方法")
#輸出 C語言中文網(wǎng)1 網(wǎng)址為: http://c.biancheng.net 通過類名直接調(diào)用實(shí)例方法 C語言中文網(wǎng)2 網(wǎng)址為: http://c.biancheng.net 通過類對象直接調(diào)用實(shí)例方法
1.封裝
簡單的理解封裝(Encapsulation),即在設(shè)計類時,刻意地將一些屬性和方法隱藏在類的內(nèi)部,這樣在使用此類時,將無法直接以“類對象.屬性名”(或者“類對象.方法名(參數(shù))”)的形式調(diào)用這些屬性(或方法),而只能用未隱藏的類方法間接操作這些隱藏的屬性和方法。
Python 類如何進(jìn)行封裝?
和其它面向?qū)ο蟮木幊陶Z言(如 C++、Java)不同,Python 類中的變量和函數(shù),不是公有的(類似 public 屬性),就是私有的(類似 private),這 2 種屬性的區(qū)別如下:
public:公有屬性的類變量和類函數(shù),在類的外部、類內(nèi)部以及子類(后續(xù)講繼承特性時會做詳細(xì)介紹)中,都可以正常訪問;
private:私有屬性的類變量和類函數(shù),只能在本類內(nèi)部使用,類的外部以及子類都無法使用。
Python 并沒有提供 public、private 這些修飾符。為了實(shí)現(xiàn)類的封裝,Python 采取了下面的方法:
默認(rèn)情況下,Python 類中的變量和方法都是公有(public)的,它們的名稱前都沒有下劃線(_);
如果類中的變量和函數(shù),其名稱以雙下劃線“”開頭,但是沒有以雙下劃線“”結(jié)尾,則該變量(函數(shù))為私有變量(私有函數(shù)),其屬性等同于
private。
封裝的具體細(xì)節(jié)參考
2.繼承和多態(tài)
在OOP(Object Oriented Programming)程序設(shè)計中,當(dāng)我們定義一個class的時候,可以從某個現(xiàn)有的class 繼承,新的class稱為子類(Subclass),而被繼承的class稱為基類、父類或超類(Base class、Super class)。
繼承有什么好處?最大的好處是子類獲得了父類的全部屬性及功能。
使用 class subclass_name(baseclass_name) 來表示繼承
class Person(object): def __init__(self,name,sex): self.name = name self.sex = sex def print_title(self): if self.sex == "male": print("man") elif self.sex == "female": print("woman") class Child(Person): # Child 繼承 Person pass May = Child("May","female") Peter = Person("Peter","male") print(May.name,May.sex,Peter.name,Peter.sex) # 子類繼承父類方法及屬性 May.print_title() Peter.print_title()
#輸出 May female Peter male woman man
isinstance() 及 issubclass()
Python 與其他語言不同點(diǎn)在于,當(dāng)我們定義一個 class 的時候,我們實(shí)際上就定義了一種數(shù)據(jù)類型。我們定義的數(shù)據(jù)類型和Python自帶的數(shù)據(jù)類型,比如str、list、dict沒什么兩樣。
Python 有兩個判斷繼承的函數(shù):isinstance() 用于檢查實(shí)例類型;issubclass() 用于檢查類繼承。參見下方示例:
class Person(object): pass class Child(Person): # Child 繼承 Person pass May = Child() Peter = Person() print(isinstance(May,Child)) # True print(isinstance(May,Person)) # True print(isinstance(Peter,Child)) # False print(isinstance(Peter,Person)) # True print(issubclass(Child,Person)) # True
在說明多態(tài)是什么之前,我們在 Child 類中重寫 print_title() 方法:若為male,print boy;若為female,print girl
class Person(object): def __init__(self,name,sex): self.name = name self.sex = sex def print_title(self): if self.sex == "male": print("man") elif self.sex == "female": print("woman") class Child(Person): # Child 繼承 Person def print_title(self): if self.sex == "male": print("boy") elif self.sex == "female": print("girl") May = Child("May","female") Peter = Person("Peter","male") print(May.name,May.sex,Peter.name,Peter.sex) May.print_title() Peter.print_title()
當(dāng)子類和父類都存在相同的 print_title()方法時,子類的 print_title() 覆蓋了父類的 print_title(),在代碼運(yùn)行時,會調(diào)用子類的 print_title()
這樣,我們就獲得了繼承的另一個好處:多態(tài)。
多態(tài)的好處就是,當(dāng)我們需要傳入更多的子類,例如新增 Teenagers、Grownups 等時,我們只需要繼承 Person 類型就可以了,而print_title()方法既可以直不重寫(即使用Person的),也可以重寫一個特有的。這就是多態(tài)的意思。調(diào)用方只管調(diào)用,不管細(xì)節(jié),而當(dāng)我們新增一種Person的子類時,只要確保新方法編寫正確,而不用管原來的代碼。這就是著名的**“開閉”原則**:
對擴(kuò)展開放(Open for extension):允許子類重寫方法函數(shù) 對修改封閉(Closed for modification):不重寫,直接繼承父類方法函數(shù)
子類重寫構(gòu)造函數(shù)
子類可以沒有構(gòu)造函數(shù),表示同父類構(gòu)造一致;子類也可重寫構(gòu)造函數(shù);現(xiàn)在,我們需要在子類 Child 中新增兩個屬性變量:mother 和 father,我們可以構(gòu)造如下(建議子類調(diào)用父類的構(gòu)造方法,參見后續(xù)代碼):
class Person(object): def __init__(self,name,sex): self.name = name self.sex = sex class Child(Person): # Child 繼承 Person def __init__(self,name,sex,mother,father): Person.__init__(self,name,sex) # 子類對父類的構(gòu)造方法的調(diào)用 self.mother = mother self.father = father May = Child("May","female","April","June") print(May.name,May.sex,May.mother,May.father)
多重繼承
多重繼承的概念應(yīng)該比較好理解,比如現(xiàn)在需要新建一個類 baby 繼承 Child , 可繼承父類及父類上層類的屬性及方法,優(yōu)先使用層類近的方法,代碼參考如下:
class Person(object): def __init__(self,name,sex): self.name = name self.sex = sex def print_title(self): if self.sex == "male": print("man") elif self.sex == "female": print("woman") class Child(Person): pass class Baby(Child): pass May = Baby("May","female") # 繼承上上層父類的屬性 print(May.name,May.sex) # May female May.print_title() #woman 可使用上上層父類的方法 class Child(Person): def print_title(self): if self.sex == "male": print("boy") elif self.sex == "female": print("girl") class Baby(Child): pass May = Baby("May","female") May.print_title() # girl 優(yōu)先使用上層類的方法
迭代:是訪問集合元素的一種方式。如果給定一個list或tuple,我們可以通過for循環(huán)來遍歷這個list或tuple,這種遍歷我們稱為迭代(Iteration)。
迭代對象: 如果類中定義了__iter__方法,且返回了一個迭代器對象, 那么稱這個創(chuàng)建的對象為可迭代對象
字符串,列表,元祖,字典,集合等等,都是可迭代對象。
(沒有__next__)
可迭代對象,則可用for循環(huán)
# 字符串,列表,元祖,字典,集合等等,都是可迭代對象 for i in [1, 2, 3]: print(i) obj = {"a": 123, "b": 456} for k in obj: print(k)
創(chuàng)建可迭代對象
class foo(object): def __iter__(self): return 迭代器對象(生成器對象) obj = foo() #obj是可迭代對象
#創(chuàng)建迭代器 class IT(object): def __init__(self): self.counter = 0 def __iter__(self): return self def __next__(self): self.counter += 1 if self.counter == 3: raise StopIteration() #創(chuàng)建可迭代器對象 class foo(object): def __iter__(self): return IT() obj = foo() #obj是可迭代對象 for item in obj: #循環(huán)可迭代對象時,內(nèi)部先執(zhí)行obj.__iter__()并獲取迭代器對象,然后再不斷的執(zhí)行迭代器對象的__next__方法 print(item)
迭代器:迭代器是一個可以記住遍歷的位置的對象
類中定義了__iter__和__next__兩個方法
__iter__返回對象本身,即self
__next__返回下一個數(shù)據(jù),如果沒有,就返回一個stopiteration 的異常。
迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結(jié)束。迭代器只能往前不會后退。
迭代器有兩個基本的方法(內(nèi)置函數(shù)):iter() 和 next() ;內(nèi)置函數(shù) iter() 將可迭代對象轉(zhuǎn)化為迭代器. 通過 next() 方法逐一讀取下一個元素
創(chuàng)建一個迭代器
創(chuàng)建迭代器共有3種方法如下:
通過python內(nèi)置函數(shù)iter()將可迭代對象轉(zhuǎn)換為迭代器
自己創(chuàng)建一個迭代器, 滿足(1)類中定義了__iter__和__next__兩個方法(2)__next__返回下一個數(shù)據(jù),如果沒有,就返回一個stopiteration> 的異常 2個條件
通過生成器(generator)創(chuàng)建
# 方法1: iter()將可迭代對象轉(zhuǎn)換為迭代器 list=[1, 2, 3, 4] it = iter(list) # 創(chuàng)建迭代器對象 #使用next()遍歷數(shù)據(jù) print (next(it)) #1 print (next(it)) #2 #使用for循環(huán)遍歷數(shù)據(jù),for循環(huán)由于簡潔,更常用 #for循環(huán)會執(zhí)行迭代器的iter并獲得返回的對象,一直反復(fù)的去執(zhí)行next(對象) for x in it: print (x, end=" ") # 3 4 print (next(it)) #StopIteration # 方法2: 創(chuàng)建一個迭代器 class MyNumbers: def __iter__(self): self.a = 1 return self def __next__(self): if self.a <= 20: x = self.a self.a += 1 return x else: raise StopIteration #通過iter()和next()訪問 myclass = MyNumbers() myiter = iter(myclass) print(next(myiter)) print(next(myiter)) print(next(myiter)) for x in myiter: print(x) print(next(myiter))
#輸出
StopIteration
1
2
3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Process finished with exit code 1
生成器:使用了 yield 的 函數(shù) 被稱為生成器(generator)
具體細(xì)節(jié)參考http://kemok4.com/article/63929.htm
相比迭代器,生成器最明顯的優(yōu)勢就是節(jié)省內(nèi)存空間,即它不會一次性生成所有的數(shù)據(jù),而是什么時候需要,什么時候生成。
創(chuàng)建一個生成器
定義一個以 yield 關(guān)鍵字標(biāo)識返回值的函數(shù);
調(diào)用剛剛創(chuàng)建的函數(shù),即可創(chuàng)建一個生成器
要想使生成器函數(shù)得以執(zhí)行,或者想使執(zhí)行完 yield 語句立即暫停的程序得以繼續(xù)執(zhí)行,有以下 2 種方式:
通過生成器(上面程序中的 num)調(diào)用 next() 內(nèi)置函數(shù)或者 next() 方法;
通過 for 循環(huán)遍歷生成器。
#創(chuàng)建了一個 num 生成器對象。顯然,和普通函數(shù)不同,intNum() 函數(shù)的返回值用的是 yield 關(guān)鍵字,而不是 return 關(guān)鍵字,此類函數(shù)又成為生成器函數(shù)。 #創(chuàng)建生成器函數(shù) def intNum(): print("開始執(zhí)行") for i in range(5): yield i print("繼續(xù)執(zhí)行") #創(chuàng)建生成器對象num num = intNum() #調(diào)用 next() 內(nèi)置函數(shù) print(next(num)) #0 #調(diào)用 __next__() 方法 print(num.__next__()) #1 #通過for循環(huán)遍歷生成器 for i in num: #2 , 3, 4 print(i)
#輸出
開始執(zhí)行
0
繼續(xù)執(zhí)行
1
繼續(xù)執(zhí)行
2
繼續(xù)執(zhí)行
3
繼續(xù)執(zhí)行
4
繼續(xù)執(zhí)行Process finished with exit code 0
除此之外,還可以使用 list() 函數(shù)和 tuple() 函數(shù),直接將生成器能生成的所有值存儲成列表或者元組的形式
num = intNum() print(list(num)) num = intNum() print(tuple(num)
#輸出
開始執(zhí)行
繼續(xù)執(zhí)行
繼續(xù)執(zhí)行
繼續(xù)執(zhí)行
繼續(xù)執(zhí)行
繼續(xù)執(zhí)行
[0, 1, 2, 3, 4]
開始執(zhí)行
繼續(xù)執(zhí)行
繼續(xù)執(zhí)行
繼續(xù)執(zhí)行
繼續(xù)執(zhí)行
繼續(xù)執(zhí)行
(0, 1, 2, 3, 4)Process finished with exit code 0
“python類的相關(guān)概念”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。