再說Python面向物件的三大特性
一、繼承
面向物件中的繼承就是繼承的類直接擁有被繼承類的屬性而不需要在自己的類體中重新再寫一遍,其中被繼承的類叫做父類、基類,繼承的類叫做派生類、子類。在Python3中如果不指定繼承哪個類,預設就會繼承Object類,而繼承了Object類的類就叫做新式類,而在python2中如果不指定繼承哪個類也不會預設去繼承Object類,而沒有繼承Object類的類就叫做經典類。經典類和新式類的不同就在於對方法的搜尋順序不同,經典類是深度優先即先找自己類內,如果沒有就找左邊第一個父類,沒找到繼續從這個父類的父類中找依次類推直到找到最上一級的父類也沒找到再找左邊第二個父類,然後再重複之前的過程,直到所有父類找一遍沒找到就報錯;而新式類是廣度優先,當下一個類可以通過其他類找到時就先不去找它,而是找繼承關係中與它的子類同級的其他類,依次類推直到最後找到object類沒有找到指定方法就報錯。新式類搜尋順序圖示如下,還可以通過類名.mro()檢視新式類繼承中的屬性搜尋順序
二、單繼承與多繼承
在其他語言中只支援單繼承即class 類名(父類名),而python支援多繼承,用逗號將多個父類隔開即class 類名(父類名1,父類名2,。。。。)
三、繼承與抽象
抽象就是把一類事物的共有特性提取出來,繼承則是把父類的屬性拿過來並且還擁有自己的屬性。抽象是包含的範圍越來越大,共性越來越少,繼承則是包含的返回越來越小,共性越來越多。我們定義父類的過程就是抽象,定義子類的過程就是繼承。
四、父類方法重寫
我們把子類有而父類沒有的方法叫做子類的派生方法,而父類有子類也有的方法叫做對父類方法的重寫,因為按照類方法的搜尋順序一個方法如果在子類中有就不會再從父類中找了,結果就是父類中的方法無法呼叫了,如果既想執行父類中的方法同時在子類中又能定義新功能,就需要先把父類中的這個方法單獨繼承過來,在python中只能使用父類名.方法名(self,父類的其他引數)的方式,在python3中可以使用super函式來實現,比如super().父類方法名(除self外的其他引數),其實在super函式中還需要傳入子類名和子類物件(在類中用self),但是我們使用時不需要特意去傳,除非在類外單獨呼叫父類的方法。注意在繼承父類方法時父類的引數除了需要在父類的方法中傳遞還需要在子類重寫的方法中傳遞
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
五、介面類
介面類是用於規範子類的方法名定義用的,繼承介面類的子類可以不存在任何邏輯上的關係但是都需要實現某些共同的方法,為了讓這些子類的方法名能夠統一以便之後呼叫這些方法時不需要關注具體的物件就用介面類規範了這些方法的名字,子類一旦繼承了介面類就必須實現介面類中定義的方法,否則在子類例項化的時候就會報錯,而介面類本身則不需要實現去實現這些方法。
1 from abc import ABCMeta,abstractmethod
2 class Payment(metaclass=ABCMeta):
3 @abstractmethod
4 def pay(self,money):pass
5
6 class Wechatpay(Payment):
7 def pay(self,money): #子類中必須定義介面類中有的方法,否則例項化會報錯
8 pass
9
10 w1=Wechatpay()
六、抽象類
抽象類的作用和介面類一樣,只是繼承它的子類一般存在一些邏輯上的關係,且抽象類中的方法可以去實現,子類在重寫時用super函式呼叫抽象類的方法即可,同時在用抽象類時使用單繼承,使用介面類時使用多繼承
七、多型
多型就是不同的物件可以呼叫相同的方法然後得到不同的結果,有點類似介面類的感覺,在python中處處體現著多型,比如不管你是列表還是字串還是數字都可以使用+和*。
八、封裝
封裝就是把類中的屬性和方法定義為私有的,方法就是在屬性名或方法名前加雙下劃線,而一旦這樣定義了屬性或方法名後,python會自動將其轉換為_類名__屬性名(方法名)的格式,在類的內部呼叫還是用雙下劃線加屬性名或方法名,在類的外部呼叫就要用_類名__屬性名(方法名)。父類的私有屬性和方法,子類無法對其進行修改。
九、類的裝飾器
property屬性裝飾器:將類內的方法的呼叫方式和屬性一樣,這個裝飾器還有和其配套的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靜態方法裝飾器:將類內的方法變成普通的函式,或者把類外的函式放到類內當作方法呼叫
class A:
@staticmethod
def sum(): #這個方法跟普通函式沒有區別
print('staticmethod')
A.sum() #用類名呼叫
--------------------------------------------------------------------------------------
staticmethod
classmethod類方法裝飾器:該方法用於操作類屬性,無法操作物件屬性
class A:
role='male'
@classmethod
def sum(cls): #用於操作類屬性
print(cls.role)
A.sum() #用類名呼叫
--------------------------------------------------------------------------------------
male
十、isinstance和type的區別以及issubclass
isinstance和type都可以用於判斷物件和指定類間的關係,但是isinstance的判斷沒有type準確,它無法正確判斷子類的物件和其父類的關係
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用於判斷給定的兩個類,前者是否是後者的子類
十一、反射
hasattr(物件或類名,‘屬性或方法名’) 判斷指定的物件或類中是否存在指定的屬性或方法,有返回True
getattr(物件或類名,'屬性或方法名') 獲取物件或類的指定屬性值或方法的記憶體地址
setattr(物件或類名,‘新屬性名’,新屬性值) 給物件或類新增新的屬性或方法
delattr(物件或類名,‘新屬性名’) 刪除之前新增的屬性
十二、類的內建方法
__doc__ :輸出類的描述資訊
__module__ :表示當前操作的物件在那個模組
__class__ : 表示當前操作的物件的類是什麼
__dict__ :檢視類或物件中的所有成員 類呼叫列印類的所有屬性,不包括例項屬性。例項呼叫列印所有例項屬性
__str__ 格式化輸出%s輸出該方法的值
__repr__ 格式化輸出%r輸出該方法的值,並且%s在沒有__str__方法時也是輸出該方法的值
__del__ del 執行該方法
__getitem__ 用物件加[]方式取值
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__ 用於建立沒有屬性的物件,呼叫object的__new__即可不需要自己實現。可以利用該方法實現單例模式
__call__ 物件加括號執行該方法
__len__ len()執行該方法
__eq__ ==運算輸出該方法的值
__hash__ hash執行該方法
Linux公社的RSS地址 : ofollow,noindex" target="_blank">https://www.linuxidc.com/rssFeed.aspx
本文永久更新連結地址: https://www.linuxidc.com/Linux/2018-10/154607.htm