課時42:魔法方法:算術運算

  • 2020 年 1 月 19 日
  • 筆記

目錄:

  一、算術運算符

  二、課時41課後習題及答案

 現在來講一個新名詞:工廠函數。Python2.2以後,對類和類型進行了統一,做法就是將int()、float()、str()、list()、tuple()這些BIF轉換為工廠函數:

>>> type(len)  <class 'builtin_function_or_method'>  >>> type(int)  <class 'type'>  >>> type(dir)  <class 'builtin_function_or_method'>  >>> type(list)  <class 'type'>

看到沒有,普通的BIF應該是<class 'builtin_function_or_method'>,而工廠函數則是<class 'type'>。大家有沒有覺得<class 'type'>很眼熟,沒錯啦,如果定義一個類:

>>> class C:      pass    >>> type(C)  <class 'type'>

它的類型也是type類型,也就是類對象,其實所謂的工廠函數,其實就是一個類對象。當你調用它們的時候,事實上就是創建一個相應的實例對象:

>>> a = int('123')  >>> b = int('345')  >>> a + b  468

現在你是不是豁然發現:原來對象是可以進行計算的!其實你早該發現這個問題了,Python中無處不對象,當在求a + b等於多少的時候,事實上Python就是在將兩個對象進行相加操作。Python的魔法方法還提供了自定義對象的數值處理,通過下面這些魔法方法的重寫,可以自定義任何對象間的算術運算。

******************

一、算術運算符

******************

 表中列舉了算術運算相關的魔法方法。

__add__(self, other)                   定義加法的行為:+  __sub__(self, other)                   定義減法的行為:-  __mul__(self, other)                   定義乘法的行為:*  __truediv__(self, other)               定義真除法的行為:/  __floordiv__(self, other)              定義整數除法的行為://  __mod__(self, other)                   定義取模演算法的行為:%  __divmod__(self, other)                定義當被 divmod() 調用時的行為  __pow__(self, other[, modulo])         定義當被 power() 調用或 ** 運算時的行為  __lshift__(self, other)                定義按位左移位的行為:<<  __rshift__(self, other)                定義按位右移位的行為:>>  __and__(self, other)                   定義按位與操作的行為:&  __xor__(self, other)                   定義按位異或操作的行為:^  __or__(self, other)                    定義按位或操作的行為:|

 舉個例子,下面定義一個比較特立獨行的類:

>>> class New_int(int):      def __add__(self,other):          return int.__sub__(self,other)      def __sub__(self,other):          return int.__add__(self,other)      >>> a = New_int(3)  >>> b = New_int(5)  >>> a + b  -2  >>> a - b  8

倘若你想自己寫程式碼,不想通過調用Python默認的方案行不行?答案是肯定的,但是要格外小心。

>>> class Try_int(int):      def __add__(self,other):          return self + other      def __sub__(self,other):          return self - other      >>> a = Try_int(1)  >>> b = Try_int(3)  >>> a + b  Traceback (most recent call last):    File "<pyshell#51>", line 1, in <module>      a + b    File "<pyshell#48>", line 3, in __add__      return self + other    File "<pyshell#48>", line 3, in __add__      return self + other    File "<pyshell#48>", line 3, in __add__      return self + other    [Previous line repeated 990 more times]  RecursionError: maximum recursion depth exceeded

為什麼會陷入無限遞歸呢?問題出在這裡:

def __add__(self,other):          return self + other

當對象涉及加法操作時,自動調用魔法方法__add__(),但看看上邊的魔法方法寫的是什麼?寫的是return self + other,也就是返回對象本身加另外一個對象,這不就又自動觸發調用__add__()方法了嗎?這樣就形成了無限遞歸。所以,要像下面這樣寫就不會觸發無限遞歸了:

>>> class New_int(int):      def __add__(self,other):          return int(self) + int(other)      def __sub__(self,other):          return int(self) - int(other)      >>> a = New_int(1)  >>> b = New_int(3)  >>> a + b  4

當對象進行相關的算術運算,自然而然就會自動觸發對應的魔法方法。

通過對魔法方法的重寫,你完全可以讓Python根據你的意願去執行:

>>> class int(int):      def __add__(self,other):          return int.__sub__(self,other)      >>> a = int('5')  >>> b = int('3')  >>> a + b  2

當然,這樣做在邏輯上是說不過去的…… emmmm

*******************************

二、課時41課後習題及答案

*******************************