溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python面向?qū)ο罂偨Y(jié)及類與正則表達(dá)式詳解

發(fā)布時(shí)間:2020-10-12 13:10:20 來(lái)源:腳本之家 閱讀:144 作者:小莫1999 欄目:開發(fā)技術(shù)

Python3 面向?qū)ο?/strong>

--------------------------------------------------------------------------------

一丶面向?qū)ο蠹夹g(shù)簡(jiǎn)介

•類(Class): 用來(lái)描述具有相同的屬性和方法的對(duì)象的集合。它定義了該集合中每個(gè)對(duì)象所共有的屬性和方法。對(duì)象是類的實(shí)例。
•方法:類中定義的函數(shù)。
•類變量:類變量在整個(gè)實(shí)例化的對(duì)象中是公用的。類變量定義在類中且在函數(shù)體之外。類變量通常不作為實(shí)例變量使用。
•數(shù)據(jù)成員:類變量或者實(shí)例變量用于處理類及其實(shí)例對(duì)象的相關(guān)的數(shù)據(jù)。
•方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對(duì)其進(jìn)行改寫,這個(gè)過(guò)程叫方法的覆蓋(override),也稱為方法的重寫。
•局部變量:定義在方法中的變量,只作用于當(dāng)前實(shí)例的類。
•實(shí)例變量:在類的聲明中,屬性是用變量來(lái)表示的。這種變量就稱為實(shí)例變量,是在類聲明的內(nèi)部但是在類的其他成員方法之外聲明的。
•繼承:即一個(gè)派生類(derived class)繼承基類(base class)的字段和方法。繼承也允許把一個(gè)派生類的對(duì)象作為一個(gè)基類對(duì)象對(duì)待。例如,有這樣一個(gè)設(shè)計(jì):一個(gè)Dog類型的對(duì)象派生自Animal類,這是模擬"是一個(gè)(is-a)"關(guān)系(例圖,Dog是一個(gè)Animal)。
•實(shí)例化:創(chuàng)建一個(gè)類的實(shí)例,類的具體對(duì)象。
•對(duì)象:通過(guò)類定義的數(shù)據(jù)結(jié)構(gòu)實(shí)例。對(duì)象包括兩個(gè)數(shù)據(jù)成員(類變量和實(shí)例變量)和方法。

和其它編程語(yǔ)言相比,Python 在盡可能不增加新的語(yǔ)法和語(yǔ)義的情況下加入了類機(jī)制。

Python中的類提供了面向?qū)ο缶幊痰乃谢竟δ埽侯惖睦^承機(jī)制允許多個(gè)基類,派生類可以覆蓋基類中的任何方法,方法中可以調(diào)用基類中的同名方法。

對(duì)象可以包含任意數(shù)量和類型的數(shù)據(jù)。

1.類中帶下劃線開頭的變量特點(diǎn)

     類中的方法,其實(shí)就是類中的函數(shù),可以分為:實(shí)例方法,類方法,靜態(tài)方法。方法和字段一樣,也是屬于類的屬性,所以也具有運(yùn)行中修改的特效, 但一般不推薦這樣做。

  我在類的基本語(yǔ)法中,介紹了構(gòu)造器方法:__init__ 、__new__;解構(gòu)器方法:__del__;

  注意,這里雖然是以兩個(gè)下劃線(__)開頭,但同時(shí)以兩個(gè)下劃線(__)結(jié)尾,這里表明其是一個(gè)‘魔法方法',關(guān)于類中的魔法方法,將起一篇進(jìn)行說(shuō)明。

  但是,如果單純只以兩個(gè)下劃線開始,則依然是私有化的意思,看代碼示例:

class Test(object):

 def __scolia__(self): # 一個(gè)類似魔術(shù)方法,并不是私有化
 return 'scolia'

 def __good(self): # 私有方法
 return 'good'
a = Test()
print a.__scolia__() # 魔法方法可以在直接訪問(wèn)
print a.__good() # 私有方法不能直接訪問(wèn)

  同樣的,和字段私有化一樣,我們也可能同特殊手段進(jìn)行強(qiáng)制訪問(wèn):

print a._Test__good()  # 強(qiáng)制訪問(wèn)

  當(dāng)然,私有方法也可以在類的內(nèi)部訪問(wèn),和私有字段一樣。

  所以說(shuō),屬性的私有化都是對(duì)訪問(wèn)入口進(jìn)行混淆,同樣的,也不建議強(qiáng)制訪問(wèn)私有屬性。

  也許這里的‘魔法方法'看起來(lái)并不‘魔法',詳情將以后解釋。

--------------------------------------------------------------------------------

實(shí)例方法:

  在 __init__ 構(gòu)造器中,提起過(guò)其是一個(gè)實(shí)例方法,實(shí)例方法的特點(diǎn)就是:

  1.方法的第一個(gè)參數(shù)必須是 self,當(dāng)然這是約定俗成的寫法,你可以將 self 換成 abc 之類的,但是為了別的程序員能看得懂,還是統(tǒng)一用 self 吧。這里的 self 代表實(shí)例本身,也就是說(shuō)如果我實(shí)例化時(shí)使用的是: a = Test() ,那么 self 就代表 a 這個(gè)實(shí)例,我們可以在很多構(gòu)造器中看到類似 self.scolia = 'good' 的寫法,其實(shí)這個(gè)寫法和在類外面 a.scolia = 'good' 效果一樣,是為了添加屬性,只不過(guò) __init__ 方法是實(shí)例化時(shí)自動(dòng)調(diào)用的函數(shù),所以適合進(jìn)行初始屬性的創(chuàng)建。

  2.實(shí)例方法在調(diào)用的時(shí)候,self 是自動(dòng)傳遞的,所以不需要我們?cè)偬幚怼?/p>

  3.實(shí)例方法一般要有實(shí)例才能調(diào)用,當(dāng)然也有特殊的調(diào)用方法。

代碼示例:

class Test(object):

 def __init__(self, a, b): # 構(gòu)造器在實(shí)例創(chuàng)建時(shí)進(jìn)行屬性的初始化
 self.a = int(a)
 self.b = int(b)

 def abc(self, c): # 實(shí)例方法
 print self.a + self.b + int(c) # 因?yàn)閟elf是自動(dòng)傳遞的,所以我們可以在實(shí)例方法中調(diào)用實(shí)例的屬性
a = Test(123, 321) # 我們只要為 a 和 b 傳參就行了
a.abc(666) # 同樣的,只要為 c 傳參

  這里,將引入一個(gè)綁定 (binding) 的概念,其主要和方法的調(diào)用有關(guān)。

  首先,我們知道方法是類的屬性,而不是實(shí)例的屬性,在上篇博文類的屬性和實(shí)例的屬性中我們也討論過(guò)這個(gè)問(wèn)題。

  其次,方法只有在其所屬的類擁有實(shí)例時(shí),才能被調(diào)用。當(dāng)一個(gè)類存在實(shí)例后,方法才被認(rèn)為是綁定到這個(gè)實(shí)例。沒(méi)有實(shí)例的時(shí)候,方法是未綁定的。

  最后,任何一個(gè)方法定義的第一個(gè)參數(shù)都是變量 self ,它表示調(diào)用此方法的實(shí)例對(duì)象。

  很明顯這里的綁定針對(duì)的是實(shí)例方法。因?yàn)槿绻麤](méi)有實(shí)例的話,self 就無(wú)法傳遞,這將導(dǎo)致參數(shù)的不足,當(dāng)然就無(wú)法調(diào)用了。

  但是,我們可以自己傳遞 self 來(lái)調(diào)用未綁定的方法。調(diào)用未綁定的方法通常是在我們繼承了一個(gè)父類后, 我們覆蓋了父類中的某個(gè)方法,但是為了實(shí)現(xiàn)代碼重用,我們又想在子類中調(diào)用父類的方法。單純的復(fù)制父類中的代碼明顯不是一個(gè)好選擇, 除了浪費(fèi)系統(tǒng)資源之外,還有可能在復(fù)制的時(shí)候出錯(cuò),而且以后修改父類的代碼之后,還要修改相應(yīng)子類中的代碼,實(shí)在太低效,這個(gè)時(shí)候就是調(diào)用未綁定方法的場(chǎng)景。

代碼示例:

class abc(object):
 def __init__(self, a):
 self.a = -int(a)

class Test(abc):
 def __init__(self, a, b):
 abc.__init__(self, a) # 調(diào)用父類的構(gòu)造器,并手動(dòng)傳遞 self
 self.b = b

 def fangfa(self):
 print self.a + self.b # 屬性 a 由父類的構(gòu)造器創(chuàng)建,b 由子類構(gòu)造器創(chuàng)建

a = Test(123, 321) # 我們只創(chuàng)建了子類的實(shí)例,而沒(méi)有創(chuàng)建父類的實(shí)例
a.fangfa()

  本來(lái)我們沒(méi)有創(chuàng)建父類的示例,是無(wú)法調(diào)用父類的實(shí)例方法的,但是我們手動(dòng)傳遞了實(shí)例方法需要的 self 參數(shù),就可以實(shí)現(xiàn)調(diào)用了。

  這里的順序是,我們創(chuàng)建了 Test 的實(shí)例,其 self 是自動(dòng)傳遞的,故 Test 的構(gòu)造方法 __init__(self, a, b) 中 self 就代表實(shí)例 a,而我們又調(diào)用了父類的 abc.__init__(self, a) 這里的 self 就是子類的實(shí)例 a ,參數(shù) a 就是我們傳的 123,而父類中 self.a = -int(a) ;最后我們可在子類的方法中調(diào)用 self.a 這個(gè)屬性。

2.Python面向?qū)ο蟮娜筇匦?/strong>

一、繼承

  面向?qū)ο笾械睦^承就是繼承的類直接擁有被繼承類的屬性而不需要在自己的類體中重新再寫一遍,其中被繼承的類叫做父類、基類,繼承的類叫做派生類、子類。在python3中如果不指定繼承哪個(gè)類,默認(rèn)就會(huì)繼承Object類,而繼承了Object類的類就叫做新式類,而在python2中如果不指定繼承哪個(gè)類也不會(huì)默認(rèn)去繼承Object類,而沒(méi)有繼承Object類的類就叫做經(jīng)典類。經(jīng)典類和新式類的不同就在于對(duì)方法的搜索順序不同,經(jīng)典類是深度優(yōu)先即先找自己類內(nèi),如果沒(méi)有就找左邊第一個(gè)父類,沒(méi)找到繼續(xù)從這個(gè)父類的父類中找依次類推直到找到最上一級(jí)的父類也沒(méi)找到再找左邊第二個(gè)父類,然后再重復(fù)之前的過(guò)程,直到所有父類找一遍沒(méi)找到就報(bào)錯(cuò);而新式類是廣度優(yōu)先,當(dāng)下一個(gè)類可以通過(guò)其他類找到時(shí)就先不去找它,而是找繼承關(guān)系中與它的子類同級(jí)的其他類,依次類推直到最后找到object類沒(méi)有找到指定方法就報(bào)錯(cuò)。新式類搜索順序圖示如下,還可以通過(guò)類名.mro()查看新式類繼承中的屬性搜索順序

Python面向?qū)ο罂偨Y(jié)及類與正則表達(dá)式詳解

 二、單繼承與多繼承

  在其他語(yǔ)言中只支持單繼承即class 類名(父類名),而python支持多繼承,用逗號(hào)將多個(gè)父類隔開即class 類名(父類名1,父類名2,。。。。)

  三、繼承與抽象

  抽象就是把一類事物的共有特性提取出來(lái),繼承則是把父類的屬性拿過(guò)來(lái)并且還擁有自己的屬性。抽象是包含的范圍越來(lái)越大,共性越來(lái)越少,繼承則是包含的返回越來(lái)越小,共性越來(lái)越多。我們定義父類的過(guò)程就是抽象,定義子類的過(guò)程就是繼承。

 四、父類方法重寫

 我們把子類有而父類沒(méi)有的方法叫做子類的派生方法,而父類有子類也有的方法叫做對(duì)父類方法的重寫,因?yàn)榘凑疹惙椒ǖ乃阉黜樞蛞粋€(gè)方法如果在子類中有就不會(huì)再?gòu)母割愔姓伊?,結(jié)果就是父類中的方法無(wú)法調(diào)用了,如果既想執(zhí)行父類中的方法同時(shí)在子類中又能定義新功能,就需要先把父類中的這個(gè)方法單獨(dú)繼承過(guò)來(lái),在python中只能使用父類名.方法名(self,父類的其他參數(shù))的方式,在python3中可以使用super函數(shù)來(lái)實(shí)現(xiàn),比如super().父類方法名(除self外的其他參數(shù)),其實(shí)在super函數(shù)中還需要傳入子類名和子類對(duì)象(在類中用self),但是我們使用時(shí)不需要特意去傳,除非在類外單獨(dú)調(diào)用父類的方法。注意在繼承父類方法時(shí)父類的參數(shù)除了需要在父類的方法中傳遞還需要在子類重寫的方法中傳遞

class Animal:
 def __init__(self,name,life_value,aggr):
 self.name=name
 self.life_value=life_value
 self.aggr=aggr
 def eat(self):
 self.life_value+=10

class Person(Animal):
 def __init__(self,money,name,life_value,aggr):
 super().__init__(name,life_value,aggr)
 self.money=money
 def attack(self,obj):
 obj.life_value-=self.aggr

  五、接口類

   接口類是用于規(guī)范子類的方法名定義用的,繼承接口類的子類可以不存在任何邏輯上的關(guān)系但是都需要實(shí)現(xiàn)某些共同的方法,為了讓這些子類的方法名能夠統(tǒng)一以便之后調(diào)用這些方法時(shí)不需要關(guān)注具體的對(duì)象就用接口類規(guī)范了這些方法的名字,子類一旦繼承了接口類就必須實(shí)現(xiàn)接口類中定義的方法,否則在子類實(shí)例化的時(shí)候就會(huì)報(bào)錯(cuò),而接口類本身則不需要實(shí)現(xiàn)去實(shí)現(xiàn)這些方法。

 from abc import ABCMeta,abstractmethod
 class Payment(metaclass=ABCMeta):
 @abstractmethod
 def pay(self,money):pass 
 class Wechatpay(Payment):
 def pay(self,money): #子類中必須定義接口類中有的方法,否則實(shí)例化會(huì)報(bào)錯(cuò)
  pass
 
 w1=Wechatpay()

  六、抽象類

   抽象類的作用和接口類一樣,只是繼承它的子類一般存在一些邏輯上的關(guān)系,且抽象類中的方法可以去實(shí)現(xiàn),子類在重寫時(shí)用super函數(shù)調(diào)用抽象類的方法即可,同時(shí)在用抽象類時(shí)使用單繼承,使用接口類時(shí)使用多繼承

  七、多態(tài)

   多態(tài)就是不同的對(duì)象可以調(diào)用相同的方法然后得到不同的結(jié)果,有點(diǎn)類似接口類的感覺(jué),在python中處處體現(xiàn)著多態(tài),比如不管你是列表還是字符串還是數(shù)字都可以使用+和*。

  八、封裝

  封裝就是把類中的屬性和方法定義為私有的,方法就是在屬性名或方法名前加雙下劃線,而一旦這樣定義了屬性或方法名后,python會(huì)自動(dòng)將其轉(zhuǎn)換為_類名__屬性名(方法名)的格式,在類的內(nèi)部調(diào)用還是用雙下劃線加屬性名或方法名,在類的外部調(diào)用就要用_類名__屬性名(方法名)。父類的私有屬性和方法,子類無(wú)法對(duì)其進(jìn)行修改。

  九、類的裝飾器

  property屬性裝飾器:將類內(nèi)的方法的調(diào)用方式和屬性一樣,這個(gè)裝飾器還有和其配套的setter、deleter。

class Demo:
 @property
 def p(self):
 print('property func')
 @p.setter
 def p(self,num):
 print('property_setter')
 @p.deleter
 def p(self):
 print('在刪除')
d=Demo()
d.p 
d.p=10
del d.p
--------------------------------------------------------------------------------------
property func
property_setter

在刪除

   staticmethod靜態(tài)方法裝飾器:將類內(nèi)的方法變成普通的函數(shù),或者把類外的函數(shù)放到類內(nèi)當(dāng)作方法調(diào)用

class A:
 @staticmethod
 def sum(): #這個(gè)方法跟普通函數(shù)沒(méi)有區(qū)別
 print('staticmethod')
A.sum() #用類名調(diào)用
--------------------------------------------------------------------------------------
staticmethod

 classmethod類方法裝飾器:該方法用于操作類屬性,無(wú)法操作對(duì)象屬性

class A:
 role='male'
 @classmethod
 def sum(cls): #用于操作類屬性
 print(cls.role)
A.sum() #用類名調(diào)用
--------------------------------------------------------------------------------------
male

  十、isinstance和type的區(qū)別以及issubclass

   isinstance和type都可以用于判斷對(duì)象和指定類間的關(guān)系,但是isinstance的判斷沒(méi)有type準(zhǔn)確,它無(wú)法正確判斷子類的對(duì)象和其父類的關(guān)系

class A:
 pass
class B(A):
 pass
b=B()
print(isinstance(b,B))
print(isinstance(b,A))
print(type(b) is B)
print(type(b) is A)
--------------------------------------------------------------------------------------
True
True
True
False

  issubclass用于判斷給定的兩個(gè)類,前者是否是后者的子類

  十一、反射

   hasattr(對(duì)象或類名,‘屬性或方法名')  判斷指定的對(duì)象或類中是否存在指定的屬性或方法,有返回True

   getattr(對(duì)象或類名,'屬性或方法名')  獲取對(duì)象或類的指定屬性值或方法的內(nèi)存地址

   setattr(對(duì)象或類名,‘新屬性名',新屬性值) 給對(duì)象或類添加新的屬性或方法

   delattr(對(duì)象或類名,‘新屬性名') 刪除之前添加的屬性

  十二、類的內(nèi)置方法

  __doc__ :輸出類的描述信息

  __module__ :表示當(dāng)前操作的對(duì)象在那個(gè)模塊

  __class__ :  表示當(dāng)前操作的對(duì)象的類是什么

  __dict__ :查看類或?qū)ο笾械乃谐蓡T  類調(diào)用打印類的所有屬性,不包括實(shí)例屬性。實(shí)例調(diào)用打印所有實(shí)例屬性

  __str__ 格式化輸出%s輸出該方法的值

  __repr__  格式化輸出%r輸出該方法的值,并且%s在沒(méi)有__str__方法時(shí)也是輸出該方法的值
  __del__  del 執(zhí)行該方法
  __getitem__  用對(duì)象加[]方式取值

class A:
    def __init__(self):
        self.names=['egon','alex','eva'] #可以是其他序列
    def __getitem__(self, item):
        print(self.names[item])

a=A()
a[1]
----------------------------------------------------------
alex

  __setitem__   添加值
  __delitem__  刪除值
  __new__ 用于創(chuàng)建沒(méi)有屬性的對(duì)象,調(diào)用object的__new__即可不需要自己實(shí)現(xiàn)??梢岳迷摲椒▽?shí)現(xiàn)單例模式
  __call__ 對(duì)象加括號(hào)執(zhí)行該方法
  __len__  len()執(zhí)行該方法
  __eq__  ==運(yùn)算輸出該方法的值

  __hash__ hash執(zhí)行該方法

二丶代碼實(shí)現(xiàn)(三維向量類)

class Vecter3:
 def __init__(self, x=0, y=0, z=0):
  self.X = x
  self.Y = y
 self.Z = z
 def __add__(self, n):
  r = Vecter3()
  r.X = self.X + n.X
  r.Y = self.Y + n.Y
  r.Z = self.Z + n.Z
  return r
 def __sub__(self, n):
  r = Vecter3()
  r.X = self.X - n.X
  r.Y = self.Y - n.Y
  r.Z = self.Z - n.Z
  return r
 def __mul__(self, n):
  r = Vecter3()
  r.X = self.X * n
  r.Y = self.Y * n
  r.Z = self.Z * n
  return r
 def __truediv__(self, n):
  r = Vecter3()
  r.X = self.X / n
  r.Y = self.Y / n
  r.Z = self.Z / n
  return r
 def __floordiv__(self, n):
  r = Vecter3()
  r.X = self.X // n
  r.Y = self.Y // n
  r.Z = self.Z // n
  return r
 def show(self):
  print((self.X,self.Y,self.Z))
 v1 = Vecter3(1,2,3)
 v2 = Vecter3(4,5,6)
 v3 = v1+v2
 v3.show()
 v4 = v1-v2
 v4.show()
 v5 = v1*3
 v5.show()
 v6 = v1/2
 v6.show()

此類可實(shí)現(xiàn)三維向量的加減乘除

運(yùn)行后為

Python面向?qū)ο罂偨Y(jié)及類與正則表達(dá)式詳解

三丶代碼實(shí)現(xiàn)(程序類)

這個(gè)程序運(yùn)用類與正則表達(dá)式匹配來(lái)寫,可以刪除重復(fù)的英文并輸出,這里輸入 This is my name

import re
class Good:
 def __init__(self,n):
 self.n = n
 def love(self):
 s1 = re.split(r' ',self.n)
 s2 = sorted(set(s1),key=s1.index)
 print(s2)
b = Good('This is is my name')#此處可自行輸入字符串
b.love()

接下來(lái)我們看運(yùn)行結(jié)果

 Python面向?qū)ο罂偨Y(jié)及類與正則表達(dá)式詳解

 總結(jié)

以上所述是小編給大家介紹的Python面向?qū)ο罂偨Y(jié)及類與正則表達(dá)式詳解,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)億速云網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI