第五十節,面向對象基本介紹

一,面向對象基礎1
c#、Java:只能用面向對象編程
Ruby、python、php:函數編程 + 面向對象php

1.面向過程編程2
  就是程序最底層的實現過程
2.函數式編程3
  就是將最底層的實現過程封裝到函數裏,調用函數的方法編程
3面向對象編程4
  就是將若干函數封裝到一個類裏,調用類來實現裏面的函數方法python

 

注意:面向對象不是全部狀況都適用 5編程

 

面向對象編程6
須要定義一個類 ,將功能函數寫在類裏,這樣類裏面的函數就叫作,實現一個類功能的方法,要使用這個類的方法時,建立這個類的對象賦值給一個變量,經過對象變量找到這個類下面的功能函數來實現(功能)的方法c#

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class fgjk: #定義一個類,在類裏寫函數來實現類的方法
    def f1(self,a): #方法1
        return a + 1
    def f2(self,b): #方法2
        pass
    def f3(self,c): #方法3
        pass

a1 = fgjk() #建立類對象賦值給一個變量
a2 = a1.f1(3) #調用類下面的一個函數傳入參數,來實現一個功能,叫作方法
print(a2) #打印出這個方法的結果

#輸出fgjk類下面的f1()方法
# 4

 

class關鍵字,定義一個類7函數式編程

功能:定義一個類函數

使用方法:class 類名稱:spa

格式:class fgjk:3d

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class fgjk: #定義一個類,在類裏寫函數來實現類的方法
    def f1(self,a): #方法1
        return a + 1
    def f2(self,b): #方法2
        pass
    def f3(self,c): #方法3
        pass

 

定義好類後,將功能函數(方法)寫在類裏,注意:類裏面的函數有一個必寫值self8指針

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class fgjk: #定義一個類,在類裏寫函數來實現類的方法
    def f1(self,a): #方法1
        return a + 1
    def f2(self,b): #方法2
        pass
    def f3(self,c): #方法3
        pass

 

self是一個形式參數,這個形式參數是用來,在執行類方法時接收類對象返回值的,9code

注意:類對象的返回值是由python自動當作實參,傳入類方法函數的self,不須要咱們寫,由python自動完成

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""定義類和類的方法"""
class fgjk: #定義一個類,在類裏寫函數來實現類的方法
    def f1(self,a): #方法1
        print("打印self接收的類對象值",self)
        return a #返回值
"""建立類的對象和是使用類的方法"""
a1 = fgjk() #建立類對象賦值給一個變量
print("打印類對象值",a1)
#注意:類對象的值是由python自動當作實參,傳入類方法函數的,不須要咱們寫,由python自動完成,至關於下面寫的a1.f1(a1,3)
a2 = a1.f1(3) #調用類下面的一個函數傳入參數,來實現一個功能,叫作方法
print("打印返回值",a2) #打印出這個方法的結果

# 輸出
# 打印類對象值 <__main__.fgjk object at 0x0000006685D37160>
# 打印self接收的類對象值 <__main__.fgjk object at 0x0000006685D37160>
# 打印返回值 3

 

定義好類和寫好函數方法後,建立這個類的對象賦值給一個變量,經過變量找到這個類下面的功能函數來實現(功能)的方法  , 建立類對象也叫作(建立Foo類的實列)10

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""定義類和類的方法"""
class fgjk: #定義一個類,在類裏寫函數來實現類的方法
    def f1(self,a): #方法1
        return a + 1
    def f2(self,b): #方法2
        pass
    def f3(self,c): #方法3
        pass

"""建立類對象和使用類的方法"""
a1 = fgjk() #建立類對象賦值給一個變量
a2 = a1.f1(3) #調用類下面的一個函數傳入參數,來實現一個功能,叫作方法
print(a2) #打印出這個方法的結果

#輸出fgjk類下面的f1()方法
# 4

 

面向對象原理圖11

 

封裝12

封裝就是給對象封裝普通字段

面向對象封裝之,在類的對象裏封裝變量和變量值,非主流方法【不推薦】13
就是在類的對象裏封裝變量和變量值,封裝後使用類函數方法時不須要傳值,在類函數方法裏經過self來獲取類對象裏的值便可

給類對象添加變量:建立對象變量.要添加的變量名稱 = 變量值  如a1.zhi =  xx

類方法函數獲取對象變量:在方法函數裏經過接收對象的self來獲取,self.添加的類對象變量名稱,這樣就能夠獲取到類對象的值

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""面向對象封裝之,給類對象封裝變量和變量值"""
class fgjk: #定義一個類,在類裏寫函數來實現類的方法
    def f1(self): #方法1
        b = self.zhi + 5 #獲取類對象裏的zhi變量的值加5
        c = b + self.zhi2 #用b結果加類對象裏的zhi2變量值
        return c
"""建立類的對象和使用類的方法"""
a1 = fgjk() #建立類對象賦值給一個變量
a1.zhi = 5 #給類對象封裝一個變量和值
a1.zhi2 = 10 #給類對象封裝一個變量和值
a2 = a1.f1() #執行類方法
print(a2) #打印出方法結果
# 輸出
# 20

面向對象封裝之,在類的對象裏封裝變量和變量值原理圖14

 

__init__()構造方法,面向對象封裝之,給類對象封裝變量和變量值,主流方法 15

__init__(self)類方法函數,若是類裏有定義__init__(self)類方法函數,建立對象後會自動執行__init__(self)方法函數的

使用方法:__init__(self,後面能夠定義變量類接收對象傳值而後封裝到對象)

就是不在從類對象那裏封裝變量和值,從類的__init__(self)方法,向對象封裝變量和值,由於只要建立對象後,python就會默認執行類的__init__(self)方法,然而對象的返回值是自動經過對象傳值給類方法的self形式參數的,因此能夠根據這個形式參數接收到的對象,向對象裏封裝變量和變量值

# -*- coding:utf-8 -*-
"""面向對象封裝之,給類對象封裝變量和變量值,主流方法"""
class fgjk: #定義一個類,在類裏寫函數來實現類的方法
    def __init__(self):
        print(self)
        self.adc = "你好" #經過self接收到的對象,向對象裏封裝變量和變量值
    def f1(self):
        print(self.adc)
"""建立類的對象和使用類的方法"""
a1 = fgjk() #建立類對象賦值給一個變量,並把類對象返回值傳給類裏面的方法函數的self形式參數
a1.f1() #執行類的方法函數
# 輸出
# <__main__.fgjk object at 0x000000A5E652C518>
# 你好

經過類方法的self給對象封裝變量原理圖16

__init__()構造方法,面向對象封裝之,給類對象封裝變量和變量值,主流方法2【推薦】17

# -*- coding:utf-8 -*-
"""面向對象封裝之,給類對象封裝變量和變量值,主流方法"""
a = "變量值"
class fgjk: #定義一個類,在類裏寫函數來實現類的方法
    def __init__(self,b):
        print(self)
        self.adc = b #經過self接收到的對象,向對象裏封裝變量和變量值
    def f1(self):
        print(self.adc)
"""建立類的對象和使用類的方法"""
a1 = fgjk(a) #建立類對象賦值給一個變量,並把類對象返回值傳給類裏面的方法函數的self形式參數
a1.f1() #執行類的方法函數
# 輸出
# <__main__.fgjk object at 0x000000A5E652C518>
# 變量值

主流方法2【推薦】原理圖18

注意:咱們通常都是用構造方法2

__del__(self)解釋器銷燬對象時自動調用,咱們只須要知道一些就行,這是python自動完成的,叫作析構方法19

 

封裝總結20

使用場景,當同一類型的方法具備相同參數時,直接封裝到對象便可

使用場景2:把類當作模板,建立多個對象(每一個對象內封裝的數據能夠不同)

建立類對象,和__init__()構造封裝對象變量,叫作初始化

給對象封裝的變量,叫作給對象建立普通字段

 

繼承21

繼承就是在定義類b時,能夠在b類名稱後面加上()括號裏寫上另一個a類的名稱,這樣b類就會繼承a類裏的方法22

1.子類(派生類)、繼承父類(基類)中的全部功能23
2.Python類能夠同時繼承多個父類(基類)(c#/Java不能夠)24

3.繼承的優先級,繼承裏有相同方法的優先級25

  子類(派生類)、和父類(基類)同時存在一個方法是時,優先找子類(派生類),

  若是是一個類繼承了多個類,並且繼承的多個類中有一樣的方法是,優先從子類(派生類)()括號裏的父類(基類)左邊優先

  若是是嵌套式繼承,也就是一個類繼承了多個基類,而且多個基類又繼承了多個基類,這時是本身自己類優先,而後是上一級基類左邊第一個優先,再者是左邊第一個基類的上級基類優先,再者是左邊第二基類優先以此類推

  也就是說,首先是自身優先,而後是基類左邊優先,而後是基類左邊深度優先,以此類推的

  若是嵌套式繼承,最後有兩個類都繼承了同一個基類,這個被兩個類繼承的類不在深度查找,是最後查找這個類的

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class lei: #定義lei類
    def __init__(self,wb = ""): #接收定義lei對象裏的傳值
        self.wb = wb #將定義lei對象裏的傳值封裝到lei對象裏
    def f1(self):
        print("f1",self.wb) #打印f1和,lei對象裏封裝的wb變量
    def f2(self):
        print("f2")
    def f3(self):
        print("f3")

class lei2(lei): #定義lei2類並繼承lei類的方法
    def __init__(self,wb2 = ""): #接收定義lei2對象裏的傳值
        self.wb2 = wb2 ##將定義lei2對象裏的傳值封裝到lei2對象裏
    def j1(self):
        print("j1")
    def j2(self):
        print("j2",self.wb2) #打印j2和,lei2對象裏封裝的wb2變量
    def j3(self):
        print("j3")

a = lei("你好") #建立lei類對象,並傳值到lei類__init__方法
a.f1() #執行類裏的f1()方法

b = lei2("我好") #建立lei2類對象,並傳值到lei2類__init__方法
b.f3() #執行lei2類繼承的lei裏的f3()方法
b.j2() #執行lei2類裏的j2()方法

# 輸出
# f1 你好
# f3
# j2 我好

繼承原理圖26

 

繼承優先級說明圖27

自身優先圖28

 

基類左邊第一個優先圖29

左邊深度優先圖30

 最後有兩個類都繼承了同一個基類,這個被兩個類繼承的類不在深度查找,是最後查找這個類的31

 

 

繼承重點,self.XXX()繼承容易錯點,若是一個類繼承了多個基類,而且基類裏有self.XXX()方法,self實際就是建立的對象,self.xxx()就是又回到了建立對象的類裏去找xxx()方法,若是建立的自身類裏沒有xxx()方法,就又從繼承基類的左邊第一個開始查找,在之深度等,以此按照前面說的優先級執行32

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class a: #定義a類
    def __init__(self,zhi = ""):
        self.zhi = zhi
    def f1(self):
        print("a")
class b: #定義b類
    def __init__(self,zhi = ""):
        self.zhi = zhi
    def b1(self):
        self.f1()
class c: #定義c類
    def __init__(self,zhi = ""):
        self.zhi = zhi
    def f1(self):
        print("c")
class d(b,c,a): #定義d類
    def __init__(self,zhi = ""):
        self.zhi = zhi
fsa = d("傳值") #建立d類對象
fsa.b1() #執行d類對象的類裏面的b1()方法,類裏面沒有b1方法,就到繼承的基類左邊第一個b類裏去找b1方法,找到b1方法執行,然而b1裏是執行的對象裏面的f1方法,這樣就又回到了d類裏去找f1方法
# 輸出
# c

self.XXX()繼承原理圖33

 

 

super()內置函數【推薦】,在一個類裏獲取上一級父類基類的,__init__方法裏的對象封裝值,注意只能獲取上一級基類的__init__方法裏的對象封裝值34

使用方法:super(子類派生類名稱,self).__init__()

格式:super(b,self).__init__()

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定義a類
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定義a類
    def __init__(self):
        self.zhi = "動物"
    def f1(self):
        print("a")
class b(a): #定義b類
    def __init__(self):
        self.zh = ""
        super(b,self).__init__() #獲取上一級父類基類的,__init__方法裏的對象封裝值
        print(self.zhi) #打印出獲取到的,上一級父類基類的,__init__方法裏的對象封裝值
    def b1(self):
        print("b")
c = b()
c.f1()
# 輸出
# 動物
# a

 

被獲取類名稱.__init__(self)在一個類裏獲取另一個類的__init__方法裏的對象封裝值,注意,能夠獲取有繼承關係的,也能夠獲取無繼承關係的類35

使用方法:被獲取類名稱.__init__(self)

格式:c.__init__(self)

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定義a類
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定義a類
    def __init__(self):
        self.zhi = "動物"
    def f1(self):
        print("a")
class b(a): #定義b類
    def __init__(self):
        self.zh = ""
        c.__init__(self) #在一個類裏獲取另一個類的__init__方法裏的對象封裝值,注意,能夠獲取有繼承關係的,也能夠獲取無繼承關係的類
        print(self.zf) #打印獲取到的,另一個類的__init__方法裏的對象封裝值
    def b1(self):
        print("b")
c = b()
c.f1()
# 輸出
# 狗shi
# a

 

多態36

多態就是多種形態

 

python自身支持多態
多態的簡單理解就是,定義一個函數,建立類對象,把類對象當作實際參數傳給函數的形式參數,在函數裏經過形式參數接收到的類對象來執行對象類裏的方法,也就是向函數傳不一樣的對象,就執行不一樣對象類的方法

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""多態,多種形態"""
class ab: #定義ab類
    def __init__(self,zhi = ""): #定義__init__方法接收類對象傳的值
        self.zhi = zhi #將類對象傳值封裝到對象裏吧,給對象封裝一個字段
    def f1(self): #定義類方法
        print(self.zhi) #打印ab類對象裏封裝的zhi字段

class cd: #定義cd類
    def __init__(self,zhi = ""): #定義__init__方法接收類對象傳的值
        self.zhi = zhi #將類對象傳值封裝到對象裏吧,給對象封裝一個字段
    def f1(self): #定義類方法
        print(self.zhi) #打印cd類對象裏封裝的zhi字段

def ef(fang): #定義一個函數,設置一個形式參數接收類對象
    fang.f1() #接收對象,並執行對象的類裏面的f1()方法

ef(ab("你好")) #執行函數,建立ab類對象當作實參傳值給ef函數
ef(cd("我好")) #執行函數,建立cd類對象當作實參傳值給ef函數

# 輸出
# 你好
# 我好

 多態原理圖37

 

面向對象的進階38

 

成員39
類下面的方法爲類的成員
對象下面的封裝字段爲對象成員

利用反射來操做類裏的成員40

hasattr()內置反射函數,到指定類查找指定方法是否存在,和到指定的對象下查找,對象下的封裝變量是否存在,或者到指定對象查找對象類裏的指定方法,存在返回True,不然返回False

注意:對象有對象指針指向了類,全部也能用hasattr()函數經過對象來查找類裏的方法,因此推薦經過對象來查找,既能夠查找類又能夠查找對象下的字段

使用方法:hasattr(要查找的類名稱或對象名稱,字符串形式要查找的方法名稱或對象封裝名稱)41

格式:hasattr(c,"f1")

到指定類查找指定方法是否存在

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定義a類
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定義a類
    def __init__(self):
        self.zhi = "動物"
    def f1(self):
        print("a")
fa = hasattr(c,"f1") #hasattr()內置函數,到指定類查找指定方法是否存在,和到指定的對象下查找,對象下的封裝變量是否存在,存在返回True,不然返回False
print(fa)
# 輸出
# True

 

到指定的對象下查找對象下的封裝變量是否存在

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定義a類
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定義a類
    def __init__(self):
        self.zhi = "動物"
    def f1(self):
        print("a")
fa = hasattr(a(),"zhi") #hasattr()內置函數,到指定類查找指定方法是否存在,和到指定的對象下查找,對象下的封裝變量是否存在,存在返回True,不然返回False
print(fa) 
# 輸出
# True

到指定對象查找對象類裏的指定方法

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定義a類
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定義a類
    def __init__(self):
        self.zhi = "動物"
    def f1(self):
        print("a")
fa = hasattr(a(),"f1") #hasattr()內置函數,到指定類查找指定方法是否存在,和到指定的對象下查找,對象下的封裝變量是否存在,存在返回True,不然返回False
print(fa)
# 輸出
# True

 

getattr()內置反射函數,到指定的對象下找到,對象下的封裝變量賦值給一個變量,或者到指定對象找到對象類裏的指定方法賦值給一個變量42

注意:對象有對象指針指向了類,全部也能用hasattr()函數經過對象來查找類裏的方法,因此推薦經過對象來查找,既能夠查找類又能夠查找對象下的字段

使用方法:getattr(要查找的對象,字符串形式要查找的方法名稱或對象封裝名稱)

格式:fa = getattr(c(),"f1")

到指定對象找到對象類裏的指定方法賦值給一個變量,並執行方法

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定義a類
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定義a類
    def __init__(self):
        self.zhi = "動物"
    def f1(self):
        print("a")
fa = getattr(c(),"f1") #getattr()內置反射函數,到指定的對象下找到,對象下的封裝變量賦值給一個變量,或者到指定對象找到對象類裏的指定方法賦值給一個變量
fa() #執行找到的類方法
# 輸出
# c

到指定的對象下找到,對象下的封裝變量賦值給一個變量

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定義a類
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定義a類
    def __init__(self):
        self.zhi = "動物"
    def f1(self):
        print("a")
fa = getattr(c(),"zf") #getattr()內置反射函數,到指定的對象下找到,對象下的封裝變量賦值給一個變量,或者到指定對象找到對象類裏的指定方法賦值給一個變量
print(fa)
# 輸出
# 狗shi

 

用反射操做面向對象成員43

根據字符串方式的面向對象模塊,和字符串方式的類方法,用反射來執行面向對象44

面向對象模塊

#!/usr/bin/env python
# -*- coding:utf8 -*-
class c: #定義a類
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定義a類
    def __init__(self):
        self.zhi = "動物"
    def f1(self):
        print("a222")

反射操做面向對象模塊裏的成員

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""根據字符串方式的面向對象模塊,和字符串方式的類方法,用反射來執行面向對象"""
a = "lib.ska.mk"    #面向對象模塊路徑
b = "f1"            #類方法名稱
c = __import__(a,fromlist=True)     #反射方式導入面向對象模塊
d = hasattr(c.a(),b)                #查找模塊裏的a類裏是否有f1方法,返回布爾值
if d:                               #判斷模塊裏的a類裏是否有f1方法
    f1 = getattr(c.a(),b)           #若是有就找到f1方法賦值給一個變量
    f1()                            #執行找到a類裏的f1方法
else:
    print("a類裏沒有f1方法")

# 輸出
# a222

 

靜態字段45

靜態字段,也就是在類裏面定義變量,提供類裏的全部方法調用,這樣能很好的實現多個類有一個相同數據的狀況46

注意:靜態字段是經過,類名稱.靜態字段名稱來訪問的,對象封裝的普通字段,是經過self.普通字段名稱來訪問的

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    shux = "動物"
    def __init__(self,zhu): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    def f1(self): #定義方法
        print(a.shux, self.zhu) #打印類的靜態字段和對象封裝的普通字段
    def f2(self): #定義方法
        print(a.shux, self.zhu) #打印類的靜態字段和對象封裝的普通字段
    def f3(self): #定義方法
        print(a.shux, self.zhu) #打印類的靜態字段和對象封裝的普通字段
s = a("") #建立對象並傳值
s.f1() #執行對象類裏的f1()方法
f = a("") #建立對象並傳值
f.f2() #執行對象類裏的f2()方法
b = a("") #建立對象並傳值
b.f3() #執行對象類裏的f3()方法
# 輸出
# 動物 貓
# 動物 狗
# 動物 豬

靜態字段原理圖47

 

靜態方法48

就是在類裏定義普通函數,函數上面用上裝飾符@staticmethod,靜態方法不須要傳self參數,靜態方法經過類來訪問,不須要建立對象就能夠訪問

@staticmethod在類裏聲明一個靜態方法49

 

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    @staticmethod #定義靜態方法
    def f1(): #靜態方法
        print("靜態方法")
    def f3(self): #定義方法
        print(a.shux, self.zhu)
a.f1()
# 輸出
# 靜態方法

 

靜態方法原理圖50

 

類方法51

就是在類裏定義一個函數,函數上面用上裝飾符@classmethod,函數裏有一個必寫形式參數cls用來接收類名稱

@classmethod在類裏聲明一個類方法52

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    @classmethod #定義類方法
    def f1(cls): #自動將類名稱傳值給cls形參
        print(cls) #打印cls接收到的類名稱
    def f3(self): #定義方法
        print(a.shux, self.zhu)
a.f1()
# 輸出
# <class '__main__.a'>

類方法原理圖53

 

特性方法54

@property特性方法55

就是在類裏定義一個普通方法函數,函數上面用上裝飾符@property,函數裏有一個必寫形式參數self用來接收對象地址,也能夠給方法封裝普通字段

特性方法與普通方法的區別:就是執行特性方法函數時不用寫()括號,特性方法就是將普通方法僞形成經過對象獲取的字段,特殊方法獲取到返回值後是能夠從新賦值的

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    @property #聲明特性方法
    def f1(self): #定義特性方法
        te = "{}方法".format(self.zhu)
        print(te)
    def f3(self): #定義方法
        print(a.shux, self.zhu)
s = a("特性")
s.f1 #執行對象類裏的f1特性方法
# 輸出
# 特性方法
s.f1 = "從新賦值" #特殊方法獲取到返回值後是能夠從新賦值的

特性方法原理圖56

 

設置特性方法:就是給特性方法設置值57

@方法名稱.setter給特性方法設置值58

就是在類裏的特性方法下面,寫一個給特性方法名稱同樣的方法函數,函數上面用上裝飾符@方法名稱.setter,在方法裏設置一個形式參數來接收,執行設置特性方法傳值,執行設置特性方法時,將特性方法 = 要設置的值便可

 

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    @property #聲明特性方法
    def f1(self): #定義特性方法
        te = "{}方法".format(self.zhu)
        print(te)
    @f1.setter  #設置特性方法
    def f1(self,v): #設置特性方法
        print(v) #打印設置的特性方法值
        self.zhu = v #將設置的特性方法值替換對象封裝的普通字段
s = a("特性")
s.f1 #執行對象類裏的f1特性方法
s.f1 = "設置特性方法值"
s.f1
# 輸出
# 特性方法
# 設置特性方法值
# 設置特性方法值方法

 設置特性方法原理圖59

 

成員修飾符60
修飾成員的使用權限對成員:靜態字段、普通字段、普通方法、靜態方法、類方法、特性方法,進行成員權限修飾61
  公有:就是沒加__修飾符的成員,既能夠在類裏面訪問,也能夠經過類或者對象外部訪問
  私有:就是加上__修飾符的成員,經過對象或者類沒法外部訪問,只能在類內部訪問,外部要想訪問必須在類的內部定義一個公有方法,在公有方法裏執行要想訪問的私有成員,經過公有方法來間接的訪問私有成員,注意:一個類的私有方法只有類本身內部能夠使用, 並且沒法被繼承。

 

__類成員修飾符,用於修飾類的成員私有權限,用了__修飾符的私有成員只有類自身內部能夠訪問。62

 靜態字段修飾符63

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    __jt = "靜態字段"
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    def f1(self):
        print(a.__jt)
    def f2(self):
        pass
#print(a.__jt) #靜態字段加修飾符後外部不能夠訪問
f = a() #定義對像
f.f1() #能夠經過類裏的f1方法間接訪問
# 輸出
# 靜態字段

普通字段修飾符64

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.__zhu = zhu #將對象傳值封裝到對象裏,封裝普通字段
    def f1(self):
        print(self.__zhu)
    def f2(self):
        pass
f = a("普通字段") #定義對象
#print(f.zhu) #普通字段加修飾符後外部不能夠訪問
f.f1() #經過類裏的f1方法能夠間接訪問對象裏封裝的普通字段
# 輸出
# 普通字段

普通方法修飾符65

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.__zhu = zhu #將對象傳值封裝到對象裏,封裝普通字段
    def __f1(self):
        print("普通方法")
    def f2(self):
        self.__f1()
f = a() #定義對象
#f.__f1() #普通方法加修飾符後外部不能夠訪問
f.f2() #經過類裏的f2方法能夠間接訪問加修飾符的f1普通方法
# 輸出
# 普通方法

靜態方法修飾符66

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.__zhu = zhu #將對象傳值封裝到對象裏,封裝普通字段
    @staticmethod #定義靜態方法
    def __f1():
        print("靜態方法")
    def f2(self):
        a.__f1()
#a.__f1() #靜態方法加修飾符後外部不能夠訪問
f = a() #定義對象
f.f2() #經過類裏的f2方法能夠間接訪問加修飾符的f1靜態方法
# 輸出
# 靜態方法

類方法修飾符67

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.__zhu = zhu #將對象傳值封裝到對象裏,封裝普通字段
    @classmethod #定義類方法
    def __f1(cls):
        print("類方法",cls)
    def f2(self):
        a.__f1()
#a.__f1() #類方法加修飾符後外部不能夠訪問
f = a() #定義對象
f.f2() #經過類裏的f2方法能夠間接訪問加修飾符的f1類方法
# 輸出
# 類方法 <class '__main__.a'>

特性方法修飾符68

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.__zhu = zhu #將對象傳值封裝到對象裏,封裝普通字段
    @property #定義特性方法
    def __f1(self):
        print("特性方法")
    def f2(self):
        self.__f1
f = a() #定義對象
#f.__f1 #特性方法加修飾符後外部不能夠訪問
f.f2() #經過類裏的f2方法能夠間接訪問加修飾符的f1特性方法
# 輸出
# 特性方法

成員修飾符之特殊手段,外部訪問類的私有成員【不到萬不得已不使用】69

方法:類名稱或者對象名稱._類名稱__私有字段名稱

格式:a._a__jt

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    __jt = "靜態字段"
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    def f1(self):
        print(a.__jt)
    def f2(self):
        pass
print(a._a__jt) #特殊手段外部訪問類的私有成員
# 輸出
# 靜態字段

 

類成員之特殊方法70

__call__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後在對象後面加上()括號,也能夠在對象變量後面加括號是同樣的,會自動執行類裏的__call__方法71

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    def __call__(self, args): #定義__call__方法
        print(args,self.zhu)
    def f2(self):
        pass
f = a("方法")("__call__")
# 輸出
# __call__ 方法
#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    def __call__(self, args): #定義__call__方法
        print(args,self.zhu)
    def f2(self):
        pass
f = a("方法")
f("__call__")
# 輸出
# __call__ 方法

 

__getitem__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後在對象後面加上[]中括號,會自動執行類裏的__getitem__方法,並將[]中括號裏的值傳給__getitem__方法的形式參數。72

注意:對象後面加上[1:2:3],也是執行類的__getitem__方法

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    def __getitem__(self, item): #建立__getitem__方法
        s = self.zhu + item #將建立對象封裝的普通字段,加上執行__getitem__方法時的傳值,相加後並返回值
        return s #返回值
    def f2(self):
        pass
f = a(10) #建立對象傳值
b = f[10] #執行__getitem__方法並傳值給__getitem__方法
print(b) #打印__getitem__方法返回值
# 輸出
# 20

 

對象後面加上[1:2:3],也是執行類的__getitem__方法 73

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    def __getitem__(self, item): #建立__getitem__方法,將[]中括號裏的數據從新封裝成一個slice對象傳給item
        print(item) #打印接收到的slice對象元素
    def f2(self):
        pass
f = a() #建立對象傳值
b = f[10:12:3] #執行__getitem__方法並傳值給__getitem__方法
print(b) #打印__getitem__方法返回值
# 輸出
# 20

 

__setitem__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後在對象後面加上[xxx]=xxx中括號等於,會自動執行類裏的__setitem__方法,並將[xxx]=xxx中括號和等於裏的值傳給__setitem__方法的形式參數74

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    def __setitem__(self, key, value): #定義__setitem__方法
        print(key,value) #打印[xxx] = xxx 傳值
    def f2(self):
        pass
f = a() #建立對象傳值
f[""] = "" #執行__setitem__方法並傳值給__setitem____方法
# 輸出
# 鍵 值

 

__delitem__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後在對象後面加上del對象名稱[xxx]中括號,會自動執行類裏的__delitem__方法,並將[xxx]中括號裏的值傳給__delitem__方法的形式參數75

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    def __delitem__(self, key): #定義__delitem__方法
        print("刪除",key) #操做[xxx]裏傳來的值
    def f2(self):
        pass
f = a() #建立對象傳值
del f[""] #執行__delitem__方法,並傳值給__delitem__方法
# 輸出
# 刪除 鍵

 

__iter__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後只要for循環對象,會自動執行類裏的__iter__方法,如__iter__方法裏是一個生成器,for循環就會循環出生成器裏的結果76

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __iter__(self): #定義__iter__方法
        yield 1 #生成器
        yield 2
        yield 3
        yield 4
    def f1(self):
        pass
s = a() #建立對象
for i in s: #循環對象
    print(i) #循環打印出生成器裏的數據
# 輸出
# 1
# 2
# 3
# 4

 

__str__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後只要print打印對象或者str(對象)時就,會自動執行類裏的__str__方法77

 

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義類
    def __init__(self,vas): #定義__init__方法,接收對象傳值
        self.fds = vas #將對象傳值封裝成對象普通字段
    def __str__(self): #定義__str__方法
        return self.fds #返回對象裏的普通字段
    def f1(self):
        pass
f = a("str方法")
print(f) #打印對象時自動執行__str__方法

b = str(f) #str(對象)時也會執行__str__方法
print(b)
# 輸出
# str方法
# str方法

 

 

__dict__查看對象或者類裏的成員78

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定義a類
    def __init__(self,zhu = ""): #初始化__init__接收對象傳值
        self.zhu = zhu #將對象傳值封裝到對象裏
    def __getitem__(self, item): #建立__getitem__方法,將[]中括號裏的數據從新封裝成一個slice對象傳給item
        print(item) #打印接收到的slice對象元素
    def f2(self):
        pass
f = a("zhi") #建立對象傳值
print(f.__dict__) #查看對象裏的成員
print(a.__dict__) #查看類裏的成員
# 輸出
# {'zhu': 'zhi'}
# {'__init__': <function a.__init__ at 0x00000036345AE510>, 'f2': <function a.f2 at 0x00000036345AE620>, '__getitem__': <function a.__getitem__ at 0x00000036345AE598>, '__weakref__': <attribute '__weakref__' of 'a' objects>, '__dict__': <attribute '__dict__' of 'a' objects>, '__module__': '__main__', '__doc__': None}

 

能夠忽略,源碼建立類原理79

 __new__ python建立類源碼方法80

 __metaclass__ python建立類源碼方法81

閱讀如下代碼:

class Foo(object):
 
    def __init__(self):
        pass
 
obj = Foo()   # obj是經過Foo類實例化的對象

上述代碼中,obj 是經過 Foo 類實例化的對象,其實,不只 obj 是一個對象,Foo類自己也是一個對象,由於在Python中一切事物都是對象

若是按照一切事物都是對象的理論:obj對象是經過執行Foo類的構造方法建立,那麼Foo類對象應該也是經過執行某個類的 構造方法 建立。

print type(obj) # 輸出:<class '__main__.Foo'>     表示,obj 對象由Foo類建立
print type(Foo) # 輸出:<type 'type'>              表示,Foo類對象由 type 類建立

因此,obj對象是Foo類的一個實例Foo類對象是 type 類的一個實例,即:Foo類對象 是經過type類的構造方法建立。

那麼,建立類就能夠有兩種方式:

普通方式

class Foo(object):
 
    def func(self):
        print 'hello wupeiqi'

特殊方式(type類的構造函數)

def func(self):
    print 'hello wupeiqi'
 
Foo = type('Foo',(object,), {'func': func})
#type第一個參數:類名
#type第二個參數:當前類的基類
#type第三個參數:類的成員

==》 類 是由 type 類實例化產生

那麼問題來了,類默認是由 type 類實例化產生,type類中如何實現的建立類?類又是如何建立對象?

答:類中有一個屬性 __metaclass__,其用來表示該類由 誰 來實例化建立,因此,咱們能夠爲 __metaclass__ 設置一個type類的派生類,從而查看 類 建立的過程。

class MyType(type):

    def __init__(self, what, bases=None, dict=None):
        super(MyType, self).__init__(what, bases, dict)

    def __call__(self, *args, **kwargs):
        obj = self.__new__(self, *args, **kwargs)

        self.__init__(obj)

class Foo(object):

    __metaclass__ = MyType

    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        return object.__new__(cls, *args, **kwargs)

# 第一階段:解釋器從上到下執行代碼建立Foo類
# 第二階段:經過Foo類建立obj對象
obj = Foo()

 

重點總結82

面向對象三大特性:83
封裝、繼承、多態

成員:84
字段:普通字段(每一個對象都有一份相同數據時)、靜態字段(每一個對象都不一樣的數據時)
方法:靜態方法(無需使用對象封裝的內容時)、類方法(須要獲取對象名稱時)、普通方法(使用對象中的數據時)
特性方法:特性方法(將方法僞形成字段時)
特殊方法:對象後寫上執行屬性,就會自動執行特殊方法

類成員訪問方法:85
經過類訪問的有:靜態字段,靜態方法,類方法
經過對象訪問的有:普通字段,普通方法,特性方法
通常有self的方法用對象訪問,無self的方法用類來訪問

成員修飾符:86
修飾成員的使用權限對成員:靜態字段、普通字段、普通方法、靜態方法、類方法、特性方法,進行成員權限修飾
公有:就是沒加__修飾符的成員,既能夠在類裏面訪問,也能夠經過類或者對象外部訪問
私有:就是加上__修飾符的成員,經過對象或者類沒法外部訪問,只能在類內部訪問,外部要想訪問必須在類的內部定義一個公有方法,在公有方法裏執行要想訪問的私有成員,經過公有方法來間接的訪問私有成員
,注意:一個類的私有方法只有類本身內部能夠使用,並且沒法被繼承。

特殊方法對應的執行屬性:87類名稱(xxx):建立對象並執行類的__init__方法對象變量(xxx):執行類的__call__方法對象變量[xxx]:執行類的__getitem__方法對象變量[x:x:x]:執行類的__getitem__方法對象變量[xxx]=xxx:執行類的__setitem__方法del對象變量[xxx]:執行類的__delitem__方法for循環對象變量:執行類的__iter__方法

相關文章
相關標籤/搜索