1. 程式人生 > >Python實戰之class類的詳解

Python實戰之class類的詳解

class 類:定義某類物件相同的功能屬性

object物件: 除了呼叫類的功能屬性,自身也擁有自身的特性

建構函式:在例項化時做一些類的初始化的工作: def __init__(self)

解構函式:在例項釋放、銷燬的時候執行,通常用於做一些收尾工作,關閉一些資料庫連線,開啟的臨時檔案(def __func__ (self):例項化物件被刪除就會執行類的該方法)

類分量:所有例項共用可以調取變數,節省開銷

例項變數:初始化例項x後,例項x自身的初始屬性

 

屬性:

例項變數(靜態屬性):初始化例項x後,賦予例項x的屬性

方法(動態屬性): 也稱之功能,所有例項都可以呼叫,類分量也可以列為方法

私有方法:把方法變成私有方法格式def __xxx(self)( 類內部可以修改呼叫,但是外部調用不了)

私有屬性:把例項變數變成私有屬,格式:self.__xxx = yyy(類內部可以修改呼叫,但是外部調用不了)

 

特徵:(封裝, 繼承, 多型)

Encapsulation封裝:在類中對資料賦值,內部可以呼叫,外部是透明的,這使類變成了一個整體,裡面包含著類的資料和方法#1私有屬性  2.私有方法

Inheritance繼承:一個類可以派生出子類,在這個父類定義的屬性,方法自動被子類繼承

父子類有相同的方法(功能):有限調取子類的方法,但是子類可以呼叫父類相同的方法執行後 在執行自己的方法。

                                                  等級相同的子類:互相不可以呼叫對方的方法

                                                  單繼承

                                                  多繼承

                                                  py2經典類是按深度優先來繼承的,新式類是按廣度優先繼承的

                                                  py3全是按廣度優先繼承

polymorphism多型:一個基類有不同的子類,每個子類實現的功能不一樣,不同程式呼叫實現功能不一樣

一個介面呼叫不同例項,介面重用,一種介面,多種實現

 

class類的繼承

父子類有相同的方法(功能):有限調取子類的方法,但是子類可以呼叫父類相同的方法執行後 在執行自己的方法。
等級相同的子類:互相不可以呼叫對方的方法
py2經典類是按深度優先來繼承的,新式類是按廣度優先繼承的
py3全是按廣度優先繼承

 

 

 

繼承類和多繼承類的基本原理

 

繼承類和多繼承類的的基本原理

1.呼叫X類的a方法,如果X類沒有a方法,會繼續從該X類的父類繼續找該方法,直到base類也沒有為止

2.X類有a方法,X類的父類也有a方法,優先執行X類的a方法,結束

3.如果我們要指定執行X類的a方法,同時也要執行X類的父類的a方法(相同的方法),需要手動X類的a方法下使用super呼叫父類的a方法即可:

class X類(父類):

    def a(message) :

        super(X類名,self).bar(message) #執行父類的bar方法

4.多繼承(廣度優先(py3:同層級找遍以後再需深入一層),深度優先(py2:父類找)

1.執行的時候 obj沒有f1該方法,那麼根據py3 的廣度規則優先從第一順位的父類A開始找f1方法,然後A內部有f1方法執行完畢以後,就應該結束了。

2.但是可以繼續其他繼承的類擁有相同的f1方法執行,就需要用到了super進行指定繼續

3.結果我們知道C類是base類(沒有父類了),C類也進行了super執行指定執行了f1方法,結果執行B類的f1方法,說明super是按照深度優先順序執行f1方法而非執行繼承的父類的f1方法)

2.同理得到結果,如果super是廣度優先執行的話,使用super執行指定的f1方法的話,那麼super會按照廣度優先順序執行f1方法,而非父類的f1方法)

問題來了,本身是深度優先模式,我們非要在某個深度的類強制指定另外一個非本身繼承的類執行其相同的方法,就需要如下操作

呼叫某個類把自身傳遞進去

得到結論:super是按照自身的順序執行的,當然我們也可以進行自己指定順序執行(指定類名.方法名(self))

從上面來看self到底是什麼,其實self就是本身該物件  == obj=Foo()如下:

兩種呼叫方法,需要注意:

1是例項化後成物件後,通過自身呼叫f1方法,self就是自身

2.是例項化以後成物件後,呼叫某類的某方法,就需要把自身物件作為self傳遞進去

兩種都一樣,一種是自動的,一種就是手動的

得出self==例項化的物件(呼叫方法的物件)

 

類自帶裝飾器

@staticmethod #靜態方法

# 加了這個靜態方法:把類的該方法跟類切斷,變成一個單純的函式

# 加了這個靜態方法:把類的該方法跟類切斷,變成一個單純的函式

# 非要說有關係,就是需要通過類呼叫

# 該方法變成函式自然就不需要self,就算有也是實參

@classmethod #類方法

  #裝飾了該裝飾器的方法self.xxx呼叫的是類變數xxx而不是self.xxx

@property #attribute屬性方法

   #裝飾了該裝飾器以後,呼叫就不能用()等於不能傳參#

@方法.setter 

#賦值方法(通常配合裝飾attribute屬性方法,新增起需要的self變數)

#裝飾了該裝飾器以後,傳參方式從obj.xx(‘實參’) 修改成obj.xx = ‘實參’

@方法.deleter

#刪除方法(通常配合裝飾attribute屬性方法,刪除指定的self變數)

#裝飾了該裝飾器以後,外部呼叫方式 del obj.xx  執行了該obj.xx方法

 

類的引數

class Xx():def method... 

Xx=類名  method=類方法  obj=例項化的XX類物件

prin(obj.__doc__)  or prin(Xx.__doc__)  # 列印類的描述資訊 (註釋的資訊)

prin(obj.__module__)   #列印該物件例項化的Xx類的絕對路徑:目錄.檔名

prin(obj.__class__ )    #列印該物件例項化的Xx類的絕對路徑+類名:<class '目錄.檔名.類名'>

obj.__call__()    #呼叫方式:obj = Xx()  obj() == obj.__call__()  #呼叫了__call__方法

print(Xx.__dict__ )  #列印該類的所有方法和功能(不包括例項變數)以字典格式顯示

print(obj.__dict__)  #列印該物件(例項)的變數,以字典格式顯示

__init__     #構造方法(初始化方法),通過類建立物件時,自動觸發執行

__del__   #析構方法,當物件在記憶體中被釋放時,自動觸發執行。(程式執行完畢會執行該方法)

__str__        #obj = Xx()  print(obj) ==執行了該Xx類的str方法 沒有就返回obj物件記憶體地址

 

類的字典方式:

__getitem__     #例項以這種格式出現yy['k1'] :自動觸發執行 __getitem__

__setitem__    #例項以這種格式出現:yy['k2'] = 'alex':自動觸發執行 __setitem__

__delitem__    #例項以這種格式出現del yy['k1']#自動觸發執行__delitem__

個人感覺非常有用

class Foo(object):

    def __init__(self):

         self,data ={}

    def __setitem__(self, key, value):

        print('__setitem__', key, value)

        self.data[key] =value

    def __getitem__(self, key):

        print('__getitem__', key)

        return self.data.get(key)

    def __delitem__(self, key):

        print('__delitem__', key)

obj = Foo()

obj['name']= 'Burgess'

print(obj.data) #結果:{'name':'Burgess'}

print(obj['name']) #結果'Burgess'

el obj[''name'']  

print(obj['name']) #結果{}

 

通過字串取值有兩種:

字典 :

dict={‘y’:’xiaohong’,’x’:’xiaoming’}  

gettest = dict[‘y’]       #取值

         #gettest == xiaohong

dict[‘z’] = ‘xiaoqiang’    #字典裡面追加新的key和值

dict={‘y’:’xiaohong’,’x’:’xiaoming’, ‘z’:’xiaoqiang}’

物件:

class Bar(object):

   def __init__(self):
        pass

   def __contains__(self, item):
        pass

   def __setitem__(self,key,value):
        pass

   def __getitem__(self,key):
        pass

   def __delitem__(self.key):
        pass
 
        



obj = Bar()

obj[‘a’] = ‘xiaoxin’ 
#這種格式自動會觸發執行Bar下面的def __setitem__方法 ,’a’ 和xiaoxin’作為實參

obj[‘c’]
#這種格式會自動觸發執行Bar下面的def __getitem__方法,’c’作為實參

del obj[‘d’]
#這種格式會自動觸發執行Bar下面的def __delitem__方法,’d’作為實參

v = ‘x’ in obj
#這種格式會自動觸發執行Bar下面的def __ contains __方法,’d’作為實參

 

類的__contains__方法示例

 

 

類的兩種建立方式

 

#普通方式

class Foo(object):

    def __init__(self, name):

         self.name = name



f = Foo("alex")

print(type(f))#檢視該例項繼承的類的名 結果顯示:<class '__main__.Foo'>

print(type(Foo))#Foo是什麼  結果顯示:<class 'type'>

 

#特殊方式

def func(self):

    print('hello Burgess')

def __init__(self,name,age):

    self.name = name

    self.age = age



Foo = type("Foo",(),{'talk': func,'__init__':__init__})

#建立類  talk:方法 __init__:方法也是建構函式

#Foo本身是類 Foo也是物件,是type的物件, 我們稱type是類的類

print(type(Foo))

f = Foo("Burgess",22)#例項化得到:例項f

f.talk()

#調取類Foo的方法talk

#{talk:func} talk的執行結果來自於調取了func的執行結果

print(f.name)