python基礎課程 第11章 類的私有方法 高級魔法師


python基礎課程 第11章 類的私有方法 高級魔法師

如果說Python的世界裡,程序員就是上帝與造物主,萬物皆為對象,那麼類就是產生對象的母體,而類的私有方法可以說是造物主為了母體在生產對象時更加高效與便捷而創造的魔法師。

造物主為每一個類都配置了這麼一個魔法師,以便於類更好的描述這個世界。

關於類的私有方法,我們通常見到它們都是被兩個下劃線包裹起來,顯得那麼卓然而立,孤傲不群像箇中世紀的魔法師一樣穿一身華麗的衣袍把自己裹起來,再帶個寬簷帽。不過在計算機世界裡這身袍子和寬簷帽有點不值錢,幾個下劃線就打發了。

這麼看起來法師帶的寬簷帽倒是挺像兩個下劃線的。

今天,我們主要講Python類的私有方法。

主要知識點:

  • 類的私有方法理解
  • 類的私有成員變量
  • 常用私有方法介紹

類的私有方法理解


<code>類的私有方法理解class Student:
	
  def __init__(self):
    """初始化方法"""
    self.name = '龍傲天'
    
  def show_name(self):
    print(self.name)
    
student = Student()
student.show_name()/<code>

通過以上的代碼我們看到了程序員設計了一個Student的類,並且寫了兩個方法。


__init__ 很明顯就是私有方法,作用是在類進行實例化時自動進行一些初始化的操作(例如設置成員變量信息),這個我們在前一章已經簡單的提到了。

私有方法不需要顯式的調用,意思是它不需要通過實例化對象名 ojb.方法名() 這樣的方式調用,二是在我們操作實例對象的時候,根據不同的情景自動運行。

show_name方法就是普通方法,用於在被顯式調用 obj.show_name() 時打印當前成員變量 name

我們先來看看代碼運行結果。


python基礎課程 第11章 類的私有方法 高級魔法師

__init__ 方法在這其中發揮了很大的用處,不過我們從實例化對象的使用上基本沒感受到它的存在。

那麼__init__方法是不是類在被實例化的時候自動調用的第一個方法呢?將來可能在面試Python程序員時考官會問到這種無聊的問題,我們可以先回答他說不是。

__new__才是最早被自動調用的內部方法,實際上是由 __new__ 來調用的 __init__。

這個問題我們需要將來在講高級教程時深入到類的生命週期時去講,在這裡我們記住 __new__ 比 __init__ 更早被調用就是了。

事實上,我們在編程時為什麼要使用私有方法,我就算不用初始化方法一樣可以用其他普通方法給對象設置成員變量啊,私有方法它究竟能帶來什麼好處?這才是縈繞在我們心頭的一個問題,作者你說魔法就魔法了,它怎麼個魔法,你來個例子吧。

光說不練假把式,我們來個實際例子。

__add__ 方法


python基礎課程 第11章 類的私有方法 高級魔法師

以上代碼,我們設計了兩個幾乎一摸一樣的類,除了名字不同之外。

然後在初始化類的時候分別傳入了參數進去,一個是數字1、一個是數字2。A和B兩個類分別接收到這些參數並作為自己的成員變量value。

然後重點來了,首先我們重寫了__add__這個私有方法,它的作用是當對象被用來做 “左加” 時(左加可以視為兩個類型相加),自動被調用。

我們看到兩個類的__add__方法裡都寫著用自己的成員變量value+obj.value,這個obj默認就是被加的對象,而obj.value自然就表示是被加的對象裡成員變量value。

那麼我們可以通過簡單的對象的加法 a+b 得到結果 3,是不是很神奇?

至於說後面兩種成員變量相加和顯式調用方法相加兩種方式我就不詳細介紹了,僅僅是用來舉例。

我們可以看到用私有方法可以讓代碼變得更加優雅,少量但是簡單容易理解的代碼完成複雜的事情,這也是Python這門語言一直以來的追求之一。


其實在這裡有個疑點,那就是為什麼我說我們是重寫了__add__這個私有方法呢?因為它本身就存在,我們相當於用自定義的代碼覆蓋了類的私有方法,下面我們來看看如果不重寫方法會是什麼樣的。


python基礎課程 第11章 類的私有方法 高級魔法師

哦豁,報錯提示我們,不支持加法操作。

通過這個簡單的例子,我們可以這麼理解,在Python的私有方法裡,很多是需要重寫特定的代碼才能實現我們想要的效果的,它被定義成私有方法只是在特定的位置會被調用,但並不意味著它已經自動幫我們寫好了代碼,這些操作都需要我們自己去寫代碼實現。

通過 __add__ 方法我們瞭解到了Python私有方法的魅力所在,那麼接下來我們就多介紹一些常用的私有方法吧。

__setattr__和___getattr__

這兩個雙胞胎通常一起出現在私有方法裡,作用是用於設置類的成員變量,而類的所有成員變量其實是存在一個叫做___dict___的成員變量裡,還是用代碼來說明一切吧。


python基礎課程 第11章 類的私有方法 高級魔法師

當我們在向對象的成員變量進行取值和賦值時,實際上是調用了對象的 __setattr__和__getattr__ 方法。

當我們對這兩個方法分別進行重寫時,實際上是在對 __dict__這個類的內部成員變量進行操作。

沒錯,類同樣由內部成員變量,比如這個 __dict__,顧名思義,它實質上就是一個字典,用於存儲所有的成員變量信息。

至於__setattr__和__getattr__ 的參數,我們現在可以簡單的理解它的格式是固定的。

__setattr__需要兩個參數,分別是鍵和值,__getattr__只需要鍵,參數多了少了都會報錯,這是由Python類的語法所規定好的,我們不能去隨意更改。

絕大部分的私有方法的參數類型和格式都是預設的,我們不能隨意增減,最多能定義變量名而已。


__doc__

這個私有成員變量用於表示類的描述信息

<code>class Foo:
    """ 
    我是Foo類的描述信息,可以用過__doc__獲取到
    """
 
print(Foo.__doc__)/<code>


python基礎課程 第11章 類的私有方法 高級魔法師

__str__

如果在類裡實現了該方法,當打印對象時,會輸出該方法內的return值。

<code>class Foo:

    def __str__(self):
        return 'Foo class信息'

foo = Foo()
print(foo)/<code>


python基礎課程 第11章 類的私有方法 高級魔法師

__repr__

該方法實現的功能和__str__是一樣的,如果兩個方法同時存在是,程序只會調用__str__,在沒有__str__時才會調用__repr__。


python基礎課程 第11章 類的私有方法 高級魔法師


我們在最開始說到可以通過__add__來進行加法,那麼有沒有比較操作符相關的私有方法呢,當我希望對比兩個對象的時候。當然有!我們可以通過操作比較運算符的一系列方法來實現目的。

比較運算符的私有方法


python基礎課程 第11章 類的私有方法 高級魔法師

以上是比較運算符的私有方法介紹,我們來嘗試寫一個可以工作的。

<code> def __gt__(self, obj):
     return self.value > obj.value/<code>

以上這段代碼的意思是返回當前類的value值是否大於目標類的value值,理論上來說會返回一個布爾值對象 (True或者False)。

來看看全部代碼和結果。


python基礎課程 第11章 類的私有方法 高級魔法師

嗯,程序如實的反應了正確的比較結果,下面我們來皮一下,修改一下__gt__的輸出結果。


python基礎課程 第11章 類的私有方法 高級魔法師

通過以上代碼我們可以發現,當我們在返回的比較表達式前面加上一個not語句後,就把結果反過來了。原來為真的變成了假,原來是假的變成了真。真亦假來假亦真,是不是有種禪意,阿基米德的棺材板都按不住了。


python基礎課程 第11章 類的私有方法 高級魔法師


輸出結果我們可以看到,重寫了__gt__ 方法的內容後,我們強行篡改了原本正確的邏輯,同樣我們也可以通過修改別的私有方法去篡改原本符合直覺的邏輯。

在這裡不是鼓勵大家去故意幹這樣的事情,而是為了提醒大家,在用到私有方法時,需要注意代碼的正確性,否則很容易在進行對象操作時出現問題。

加減乘除的私有方法

之前提到的用於進行加法的__add__私有方法,那麼它的兄弟姐們還有以下。

<code>__add__ # 用於加法 
__sub__ # 用於減法
__mul__ # 用於乘法
__truediv__ #用於除法/<code>

以下是這幾個方法的實現代碼案例,感興趣的朋友可以自行運行研究。

<code>    # 加法
    def __add__(self, obj):
        return self.value+obj.value

    # 減法
    def __sub__(self, obj):
        return self.value-obj.value

    # 乘法
    def __mul__(self,obj):
        return self.value*obj.value

    # 除法
    def __truediv__(self,obj):
        return self.value/obj.value/<code>

總結

聰明的你一定會想到,我們可以對這些私有方法進行重寫,然後優化其輸出結果,比如對所有除法進行自動四捨五入操作再返回,避免每次做除法都需要四捨五入。

關於Python類的私有方法暫時就講到這,其實本章知識也只能起一個拋磚引玉的作用,要延展開來講還需要講很多東西,包括對象的生命週期,如何進行垃圾回收,元類等等。

這些餘下的內容我們將在另一個系列《Pyton進階教程》中提到,在基礎教程裡就不讓再給大家添加更多的困惑了。

我們在現階段只需要明白Pyhton類的私有方法能幹以下幾件事情。

  • 新建當前類本身不支持的操作
  • 重寫類的基本操作
  • 讓類的代碼變得優雅
  • 更好的抽象現實世界

類的私有方法有很多好處,但是我們並不是為了使用而使用,僅僅在恰當的時候使用它即可,其實很多時候我們完全不需要它們一樣可以設計類,只不過我們需要做的它們正確的用處就是了。

歡迎關注我 “紙飛機編程”,獲取更多有趣的python教程信息。


分享到:


相關文章: