1. 程式人生 > >面向對象編程——類(class)1

面向對象編程——類(class)1

del delet tab rep 函數名 多態 ons static 基礎上

一、函數式編程 與 面向對象編程

def 函數名(參數):
    pass


class 類名:
    def 函數名(self,參數):       # self必填
        pass

z1 = 類名()    # 這時,調用對象 z1,self參數即為 z1

例1:

class bar:
    def foo(self,arg):
        print(self,arg)

z1 = bar()
print(z1)               # <__main__.bar object at 0x0000019BC3088D30>
z1.foo(‘wjz‘)           # <__main__.bar object at 0x0000019BC3088D30> wjz

z2 = bar()
print(z2)               # <__main__.bar object at 0x0000019BC306B358>
z2.foo(‘wjk‘)           # <__main__.bar object at 0x0000019BC306B358> wjk

從上面的例子可以看出,self 就是當前調用的對象(即使後面繼承時);

例2:

class bar:
    def foo(self,arg):
        print(self.job,arg)

z1 = bar()
z1.job = ‘IT‘
z1.foo(‘wjz‘)           # IT wjz

z2 = bar()
z2.job = ‘IT‘
z2.foo(‘wjk‘)           # IT wjk    

從上面可以看出,當向對象存儲變量時,它會把該變量傳給類裏面的方法;

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

1. 封裝

構造方法:

當 obj = 類名()  時,實際上是做了兩件事:
    在內存中開辟空間,創建對象;
    通過對象,自動執行了一個方法:__init__方法(別名:構造方法)。

把公用的變量封裝到init方法中。 例如:

class DataBaseHelper:
    def __init__(self,ip,port,username,password):
        self.ip = ip
        self.port = port
        self.username = username
        self.password = password

    def insert(self):
        pass

    def delete(self):
        pass

    def update(self):
        pass

    def select(self):
        pass

適用場景:如果多個函數都用一些共同參數,則適合面向對象來做。例如上面數據庫操作;

2. 繼承

舉例:

class f:
    def f1(self):
        print("in the f.f1")

class s(f):                     #這裏加一個括號,指明該類的父類(基類);子類(派生類)會繼承父類的方法;s類中找不到發方法,會去f類中找。
    def s1(self):
        print("in the s.s1")

    def f1(self):
        super(s,self).f1()      # 這裏super(s,self) 表示是s的父類;
        f.f1(self)              # 這個等效上面這句 super(s,self).f1();註意,一定不能忘記self          
        print("in the s.f1")

z = s()
z.f1()

多繼承: 如果子類繼承多個父類,則排在前面的父類優先;如:

class father1:
    def a1(self):
        print("in the f1.a1")

class father2:
    def a1(self):
        print("in the f2.a1")

class son(father1,father2):         # father1在前面,優先繼承;
    def s1(self):
        print("in the son.s1")

z = son()
z.a1()                  # 等效 son.a1(z)  打印 in the f1.ar   此時,father1和father2都有a1方法,並且son的父類有兩個,則按順序優先。

上面例子中,假如father1中沒有a1方法,而father2有。但是father1的父類有a1,則繼續在father1的父類中查找。都沒有時,才會去father2。但是,如果father0是father1和father2共同的父類,則會最後繼承共同的父類。如圖:

技術分享圖片

技術分享圖片

3. 多態

python中,原生多態。這個不重要,先忽略吧。

三、 類

類成員

類(class)的成員有字段、方法;其實還有一個屬性

  • 字段分為靜態字段、普通字段;
  • 方法分為構造方法、靜態方法、普通方法、類方法;

1. 字段

在類中定義的變量,稱為靜態字段,屬於類,保存在類中,可以通過類或者對象訪問;

在類中的方法中定義的字段,稱為普通字段,屬於對象,保存在對象中,只能通過對象訪問;

如下:

  • class make:
        port = 22                       # 靜態字段
        def __init__(self,ip,username,passwd):
            self.ip = ip                # 普通字段
            self.username = username
            self.passwd = passwd
    
    z1 = make(‘1.1.1.1‘,‘root‘,‘123456‘)
    print(z1.ip,z1.username,z1.passwd,z1.port)      # 打印 1.1.1.1 root 123456 22
    
    z2 = make(‘2.2.2.2‘,‘admin‘,‘admin‘)
    print(z2.ip,z2.username,z2.passwd,z2.port)      # 打印 2.2.2.2 admin admin 22
    
    print(make.port)                                # 打印 22      可見,靜態字段屬於類,同時也可以通過類對應的對象取得(因為對象通過類對象指針指向該類)。
    

2. 方法

構造方法:在上面面向對象三大特性之封裝章節已經提到,即init方法;self是必須的;

普通方法:和構造方法一樣,只是名字不是 init的方法就是普通方法;由對象調用,也可以通過類進行調用(必須指定self對象),self是必須的;

靜態方法:在普通方法前面加上裝飾器 staticmethod,即是靜態方法;但是有個區別:self不是必須的;普通方法調用時,self就是當前調用對象;而靜態方法中,如果指定了self,則必須指定self才可以;由類或對象(對象調用其實是根據類對象指針,通過類進行調用)調用;

類方法:在普通方法前面加上裝飾器 classmethod,即是類方法;類方法中,一般不使用self,而是寫成 cls,cls為當前類;由類直接調用;類方法和靜態方法沒有太大區別;

例如:

  • class make:
    
        def __init__(self):         # 構造方法
            pass
    
        def upload(self):           # 普通方法
            pass
    
        @staticmethod
        def status(self):           # 靜態方法,self不是必須的,可以不要self;
            pass
    
        @classmethod
        def classmd(cls):           # 類方法,這裏一般寫cls
            print(cls)
            pass
    
    make.classmd()              # 打印結果和 print(make)一樣。
    

3.屬性

說類的成員有兩種。其實還有一種,定義像方法,調用像字段;我們叫它 屬性

這種屬性還可以修改、刪除;其實並不是真的刪除,只是偽造字段的操作(修改、刪除)

  • class make:
    
        @property
        def its(self):              # 定義屬性,如果定義了property之後,後面還有getter,則優先執行getter;如果沒有定義getter,則調用時執行property
            print("property")
            return 1
    
        @its.getter
        def its(self):              # 優先級高於property;
            print("getter")
    
        @its.setter
        def its(self,value):              # 定義屬性its可以修改
            print(value,"setter")
    
        @its.deleter
        def its(self):              # 定義屬性its可以刪除
            print("delete")
    
    obj = make()
    r = obj.its                 # obj.its像是調用字段,但是its定義時像方法;
    print(r)                # 返回 1
    
    obj.its = 123456            # 看似是更改,其實是找到 its.setter,然後執行。123456當做參數傳給 its.setter
    
    del obj.its                 # 看似是刪除,其實是找到its.deleter,然後執行
    

在上面的基礎上補充:

class make:
    @property
    def f1(self):
        print("in the f1")
        return 123

    @f1.getter
    def f1get(self):
        print("in the f1getter")
        return 00

    @f1.setter
    def f1set(self,value):
        print("in the f1setter",value)
        return 11

    @f1.deleter
    def f1del(self):
        print("in the f1deleter")
        return 22

    @f1get.fget                     # 這裏可以執行 @property修飾的方法f1;
    def f2(self):
        print("in the f2")
        return 456

    @f1set.fset
    def f3(self):
        print("in the f3")
        return 789

    @f1del.fdel
    def f4(self):
        print("in the f4")
        return 000

我們不調用類,只是定義這個類,這時:

        @f1get.fget 會自動執行 f1get方法;

        @f1set.fset 會自動執行 f1set方法;

        @f1del.fdel 會自動執行 f1del方法;

三個是相同的原理,註意:fget可以執行 property、getter的對象;fset只可以執行setter的對象;fdel只可以執行deleter的對象。

這裏就拿fget舉例:

技術分享圖片

另外:

def f1(self):
    return 123 
per = property(fget=f1)

------ 上下兩部分等效 ------

@property
def per(self):
    return 123

同理,

class make:
def f1(self):
    print("in f1")
    return 123

def f2(self,val):
    print("in f2",val)
    return 456
per = property(fget=f1,fset=f2)         # 這裏就是關鍵字參數,fget/fset可以省略,就是位置參數;即,fget、fset、fdel順序。property(fget,fset,fdel,doc="描述")

z = make()
z.f1 = 123

------ 上下兩部分等效 ------

class make:
    @property
    def f1(self):
        print("in f1")
        return 123


    @f1.setter
    def f1(self,val):
        print("in f2",val)
        return 456

z = make()
z.f1 = 123

面向對象編程——類(class)1