#5 Python面向對象(四)

前言

本節將是Python面向對象的最後一篇博文了,這節將記錄類的特殊方法、特殊成員方法、舊類和新類的不同,以及一些其他知識。Go!

一、類的特殊方法

Python有三種特殊方法:實例方法、靜態方法、類方法。如果你讀過一些源代碼,你一定疑惑過這些代碼:@staticmethod、@classmethod,前面見到的所有方法都是實例方法,實例方法的第一個參數為實例本身(self),由於實例方法經過前面幾節已經掌握,所有本節將會熟悉剩下的兩種特殊方法

1.1 靜態方法

之前在類中編寫的各種方法其實都是屬於實例方法,每一個方法的第一個參數是實例本身(self),實例方法固然好用,但是在開發中,需要一些這樣的方法:與類有關,在使用時不需要引用類和實例,也就是不能訪問類變量和實例變量。這些方法通常用來作全局的配置方法,使代碼更加簡潔和安全。

1.1.1 創建靜態方法

在類中的方法的前面使用裝飾器: @staticmethod 即可,靜態方法已經和普通函數沒有太大區別,唯一的區別就是靜態方法要通過對象來訪問,看例:

 1 class Teacher:
 2     def __init__(self, name, gender):
 3         self.name = name
 4         self.gender = gender
 5 
 6     def talk(self):
 7         print('I am {}'.format(self.name))
 8 
 9     @staticmethod    # 創建 is_man 靜態方法
10     def is_man(gender):
11         if gender == 'male':
12             return 1
13         return 0

通過上例可以看到靜態方法的創建比較簡單,基本上已經和類無關了,按照普通的函數創建即可

1.1.2 調用靜態方法

靜態方法與函數的區別就是調用方式不同,函數直接調用即可,但是靜態方法多多少少和類還是有一些關係的,那就是調用時需要對象來調用:

zhangsan = Teacher('zhangsan', 'male')

print(zhangsan.is_man('male'))


# 運行結果:
1

注意:靜態方法無法調用類變量和實例變量,這裏就不作演示了。

『防抄襲:讀者請忽略這段文字,文章作者是博客園的MinuteSheep

但是靜態方法通常並不會在類外調用靜態方法,而是直接在類內作為全局配置方法使用,例如:

 1 class Teacher:
 2     def __init__(self, name, gender):
 3         self.name = name
 4         self.gender = gender
 5 
 6     def talk(self):
 7         print('I am {}'.format(self.name))
 8 
 9     @staticmethod
10     def is_man(gender):
11         if gender == 'male':
12             return 1
13         return 0
14 
15     def eat(self):
16         flag = self.is_man(self.gender)   # 作為全局配置使用
17         if flag:
18             print('I am man, I will eat 2 buns')
19         else:
20             print('I am woman, I will eat 1 bun')
21 
22 
23 zhangsan = Teacher('zhangsan', 'male')
24 
25 zhangsan.eat()
# 運行結果:
I am man, I will eat 2 buns

1.1.3 繼承靜態方法

如果超類中有靜態方法時,子類繼承時會發生什麼呢?

class Teacher(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

    @staticmethod
    def is_man(gender):
        if gender == 'male':
            return 1
        return 0

    def eat(self):
        flag = self.is_man(self.gender)   # 作為全局配置使用
        if flag:
            print('I am {}, I will eat 2 buns'.format(flag))
        else:
            print('I am {}, I will eat 1 bun'.formar(flag))


class Chinese(Teacher):
    '''
    創建一個語文老師類,
    繼承Teacher
    '''

    def __init__(self, name, gender):
        super().__init__(name, gender)

    @staticmethod   # 改寫超類的靜態方法
    def is_man(gender):
        if gender == 'male':
            return 'man'
        return 'woman'


zhangsan = Chinese('zhangsan', 'male')

zhangsan.eat()

繼承后將超類靜態方法改寫,運行結果j將按照子類的靜態方法運行,結果如下:

# 運行結果:
I am man, I will eat 2 buns

# 而不是按照超類的靜態方法
# I am 1,I will eat 2 buns

1.2 類方法

 類方法,顧名思義是一種直接作用於類的方法。類方法和實例方法的區別就在於:類方法只能訪問類變量,不能訪問實例變量。

1.2.1 創建類方法

在類中的方法前面使用裝飾器: @classmethod 即可,類方法和實例方法格式相似,類方法第一個參數必須是類本身(cls),看例:

class Teacher(object):
    food = 'bun'

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

    @classmethod   # 創建類方法 eat
    def eat(cls):
        print(cls.food)

通過上面代碼可以看到,類方法的第一個參數為類本身,習慣上用cls表示,當然也可以用其他單詞表示(這一點與self類似)

1.2.2 調用類方法

類方法的調用與實例方法無異,看例:

zhangsan = Teacher('zhangsan', 'male')
zhangsan.eat()


# 運行結果:
bun

注意:類方法只能調用類變量,不能調用實例變量,這裏就不作演示了

『防抄襲:讀者請忽略這段文字,文章作者是博客園的MinuteSheep

類方法經常出現在源代碼中,通常用來為類傳入新的參數。

二、類的特殊成員方法

什麼事特殊成員方法呢?其實你已經見過了,那就是類似__init__這樣 __方法__ 形式的方法

2.1 常用的特殊成員方法

__init__   「構造函數,當實例化類對象時,會自動調用該方法」

class Test:
    def __init__(self):
        print('實例化類對象后就會運行我')

Test()

# 運行結果:
實例化類對象后就會運行我

__del__   「析構函數,當類對象在內存中被釋放時(也就是類對象運行完后),會自動調用該方法」

class Test:
    def __del__(self):
        print('類對象釋放后就會運行我')

Test()


# 運行結果:
類對象釋放后就會運行我

__call__   「call方法,在類或者對象后加括號執行該方法」

class Test:
    def __call__(self):
        print('我是博客園MinuteSheep,神馬文庫抄襲我的博文,不要臉')


Test()()
# 或者
# obj = Test()
# obj()

# 運行結果:
我是博客園MinuteSheep,神馬文庫抄襲我的博文,不要臉

__dict__   「dict方法,查看類或者對象的所有成員信息」

class Test:
x = 1000 y = 'MS' print(Test.__dict__) # 運行結果: {'__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Test' objects>, 'x': 1000, '__doc__': None, 'y': 'MS', '__dict__': <attribute '__dict__' of 'Test' objects>}

__doc__   「doc方法,查看類的描述信息」

class Test:
    '''
    這裡是類的描述信息
    '''
    x = 1000
    y = 'MS'


print(Test.__doc__)


# 運行結果:

    這裡是類的描述信息

三、舊類與新類

Python3中,只有新類,舊類以及被移除, class 類名: 和 class 類名(object): 都是新類;Python2中, class 類名: 是舊類, class 類名(object): 是新類

對舊類和新類了解一下即可

3.1 舊類與新類的區別

舊類:深度優先

新類:廣度優先

 1 # 在Python2中
 2 
 3 
 4 class A:
 5     pass
 6 
 7 
 8 class B(A):
 9     pass
10 
11 
12 class C(B):
13     pass
14 
15 
16 class D(A, B, C):
17     pass
18 
19 
20 D()

在Python2中,上述代碼的調用順序為:D->A->B->A->C->B->A

明顯是深度優先

 1 # 在Python2中
 2 
 3 
 4 class A(object):
 5     pass
 6 
 7 
 8 class B(A):
 9     pass
10 
11 
12 class C(B):
13     pass
14 
15 
16 class D(A, B, C):
17     pass
18 
19 
20 D()

在Python2中,上訴代碼的調用順序為:D->A->B->C->A->B->A->object

明顯是廣度優先

四、其他知識

4.1 私有成員和私有方法

接觸類這麼久了,你一定發現了又的方法和成員沒有下劃線,有的方法和成員只有一條下劃線,有的方法和成員首尾各有兩條下劃線,這到底是什麼含義呢?

  • 無下劃線 foo:表示普通方法和成員

  • 一條下劃線 _foo:表示被保護方法和成員,不能被 from xxx import _foo 導入

  • 兩條下劃線 __foo:表示私有方法和成員,只運行類本身進行訪問

  • 首尾各兩條下劃線 __foo__:表示特殊方法,一般由系統自定義

結語

Python面向對象的知識到此結束,多加理解和聯繫才能真正掌握面向對象的知識,拜拜~

点赞

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *