摘要:一運算符重載基礎運算符重載對已有的運算符進行重新定義,賦予其另一種功能,以適應不同的數(shù)據(jù)類型。重載一元運算符重載一元運算符只需實現(xiàn)相應的特殊方法,這些特殊方法只有一個參數(shù)。
導語:本文章記錄了本人在學習Python基礎之面向?qū)ο笃闹攸c知識及個人心得,打算入門Python的朋友們可以來一起學習并交流。
本文重點:
1、掌握運算符重載的定義和作用,以及Python對其的內(nèi)部限制;一、運算符重載基礎
2、掌握一元運算符重載設計思路;
3、理解中綴運算符重載過程中鴨子類型和白鵝類型思想的運用并掌握。
運算符重載:對已有的運算符進行重新定義,賦予其另一種功能,以適應不同的數(shù)據(jù)類型。
重載的作用:令用戶定義的對象能夠使用中綴運算符(如 + 和 | )或一元運算符(如 - 和 ~ )等運算符。
為了做好靈活性、可用性和安全性方面的平衡,Python對運算符重載施加了一些限制:
不能重載內(nèi)置類型的運算符;
能新建運算符,只能重載現(xiàn)有運算符;
某些運算符不能重載,如is、and、or和not(不過位運算符&、| 和 ~可以)。
二、一元運算符 1、常見的一元運算符-(__neg__),一元取負算術(shù)運算符。例:若 x 是 -2,則 -x==2。
+(__pos__),一元取正算術(shù)運算符。通常x==+x。
~(__invert__),對整數(shù)按位取反,~x== -(x+1)。例:若 x 是 -2,則 ~x==1。
另外,Python語言參考手冊將內(nèi)置的abs()函數(shù)列為一元運算符,它對應的特殊方法是__abs__。
2、重載一元運算符重載一元運算符只需實現(xiàn)相應的特殊方法,這些特殊方法只有self一個參數(shù)。
重載應遵循運算符的一個基本規(guī)則:始終返回一個新對象。
即,不能修改self,要創(chuàng)建并返回合適類型的新實例。
下面我們以第10章的多維向量類為例重載一元運算符:
import math class Vector: #排版需要省略中間代碼 def __abs__(self): return math.sqrt(sum(x*x for x in self)) def __neg__(self): return Vector(-x for x in self) def __pos__(self): return Vector(self) def __invert__(self): return Vector(-x-1 for x in self)3、x和+x不相等的情況
算術(shù)運算上下文的精度變化可能導致 x 不等于 +x
Python 3.4 為 Decimal 算術(shù)運算設定的默認精度是28,這里因為+x使用上下文的精度導致相等性判斷返回False。
counter實例不含零值和負值計算器
通過上面的實例能夠看到counter實例ct經(jīng)過零值和負值的賦值之后,再經(jīng)過+x運算后發(fā)現(xiàn)ct實例中的非負數(shù)對象均消失了。事實上一元運算符 + 等同于加上一個空 Counter。當Counter相加時,Python解釋器從實用性角度出發(fā)會把負值和零值的計數(shù)從結(jié)果中剔除。
現(xiàn)在我們?nèi)砸缘?0章的多維向量為例進行中綴運算符加號“+”的重載。
重載加法的目標分析:
當多維向量類是操作數(shù)時,多維向量應支持與同類向量的加法;
同時多維向量類還應支持與可迭代對象的加法;
此外當可迭代對象是操作數(shù)的時候,多維對象應具備__radd__如此來調(diào)用多維向量類中的__add__方法。
重載加法的流程圖設計:
設計的重點在于采用鴨子類型思想。當多維向量類與非數(shù)值類相加時,多維向量類無法處理異類加法運算可以將加法運算交給右操作數(shù)的類處理。因為右操作數(shù)存在可以處理這種異類加法的可能。
重載加法的代碼實現(xiàn):
from itertools import zip_longest class Vector: #排版需要省略中間代碼 def __add__(self, other): try: return Vector(a+b for a,b in zip_longest(self,other,fillvalue=0)) except TypeError: return NotImplemented def __radd__(self, other): return self+other
2、重載乘法__mul__
重載加法的目標分析:
當多維向量類是操作數(shù)時,多維向量應支持與同類向量的乘法;
同時多維向量類還應支持與可迭代對象的加法;
此外當可迭代對象是操作數(shù)的時候,多維對象應具備__rmul__如此來調(diào)用多維向量類中的__mul__方法。
注意:我們對多維向量重載的乘法是針對數(shù)論中的實數(shù)類型進行運算,此時可以采用白鵝類型顯式檢查對象的抽象基類是否為numbers.Real,代碼實現(xiàn)如下:
import numbers class Vector: #排版需要省略中間代碼 def __mul__(self, other): if isinstance(other,numbers.Real): return Vector(x*other for x in self) else: return NotImplemented def __rmul__(self, other): return self*other
Tips:一般來說只有當處理與self不同類型的操作數(shù)時,需要創(chuàng)建反向方法處理。否則沒有必要創(chuàng)建反向方法。
四、比較運算符Python 解釋器對眾多比較運算符(==、 !=、 >、 <、 >=、 <=) 的處理與前文類似, 不過在兩個方面有重大區(qū)別。
正向和反向調(diào)用使用的是同一系列方法。這方面的規(guī)則如下表所示。例如,對 == 來說,正向和反向調(diào)用都是 _eq_ 方法,只是把參數(shù)對調(diào)了;而正向的 _gt_ 方法調(diào)用的是反向的 __lt__方法, 并把參數(shù)對調(diào)。
對 == 和 != 來說,如果反向調(diào)用失敗,Python 會比較對象的 ID,而不拋出 TypeError。
1、重載等號__eq__現(xiàn)在我們?nèi)砸缘?0章的多維向量為例進行中綴運算符等號“=”的重載。
重載等號的返回為True的條件:
等號兩端對象為同類對象;
等號兩端對象中的每個元素都必須對應相等。
注意:若Vector處理等號不為True,應該返回NotImplemented交由Python處理。如果反向調(diào)用返回 NotImplemented,Python 會使用后備機制比較對象的 ID,作最后一搏。
重載等號的代碼實現(xiàn)如下:
class Vector: #排版需要省略中間代碼 def __eq__(self, other): if isinstance(other,Vector): return len(self)==len(other) and all(x==y for x,y in zip(self,other)) else: return NotImplemented2、了解object中__ne__的實現(xiàn)
def __ne__(self, other): eq_result = self == other if eq_result is NotImplemented: return NotImplemented else: return not eq_result五、增量賦值運算符 1、重載加等于__iadd__
現(xiàn)在我們?nèi)砸缘?0章的多維向量為例進行中綴運算符加等于“+=”的重載。
重載加等于設計要求:
加等于右側(cè)的對象與左側(cè)的Vector類是同類對象或可迭代對象;
否則拋出TypeError,顯示無法進行加等于計算。
下面以BingoCage的子類AddableBingoCage為例實現(xiàn)__iadd__,大家不必在意這個子類,重點在于理解__iadd__實現(xiàn)的思路:
import itertools from tombola import Tombola from bingo import BingoCage class AddableBingoCage(BingoCage): def __add__(self, other): if isinstance(other, Tombola): return AddableBingoCage(self.inspect() + other.inspect()) #self.inspect()繼承自BingoCage,返回當前元素組成的有序元組。 else: return NotImplemented def __iadd__(self, other): if isinstance(other, Tombola): other_iterable = other.inspect() else: try: other_iterable = iter(other) except TypeError: self_cls = type(self).__name__ msg = "right operand in += must be {!r} or an iterable" raise TypeError(msg.format(self_cls)) self.load(other_iterable) return self
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/44565.html
摘要:導語本文章匯總了本人在學習基礎之緒論篇數(shù)據(jù)結(jié)構(gòu)篇函數(shù)篇面向?qū)ο笃刂屏鞒唐驮幊唐獙W習筆記的鏈接,打算入門的朋友們可以按需查看并交流。 導語:本文章匯總了本人在學習Python基礎之緒論篇、數(shù)據(jù)結(jié)構(gòu)篇、函數(shù)篇、面向?qū)ο笃?、控制流程篇和元編程篇學習筆記的鏈接,打算入門Python的朋友們可以按需查看并交流。 第一部分:緒論篇 1、Python數(shù)據(jù)模型 第二部分:數(shù)據(jù)結(jié)構(gòu)篇 2、序列構(gòu)成...
摘要:前言數(shù)據(jù)模型其實是對框架的描述,它規(guī)范了這門語言自身構(gòu)件模塊的接口,這些模塊包括但不限于序列迭代器函數(shù)類和上下文管理器。上述類實現(xiàn)了方法,它可用于需要布爾值的上下文中等。但多虧了它是特殊方法,我們也可以把用于自定義數(shù)據(jù)類型。 《流暢的Python》筆記。本篇是Python進階篇的開始。本篇主要是對Python特殊方法的概述。 1. 前言 數(shù)據(jù)模型其實是對Python框架的描述,它規(guī)范了...
摘要:找到模塊文件之后,將其編譯成字節(jié)碼,就是那個文件里面的關(guān)于字節(jié)碼,下面會介紹,請繼續(xù)閱讀。當然,如果根本就沒有找到同名的源文件,只有字節(jié)碼文件,那么就只能運行這個了。執(zhí)行就是前面已經(jīng)編譯的模塊字節(jié)碼文件,順理成章要執(zhí)行了。 不管是用import還是用from mmmm import *的方式導入模塊,當程序運行之后,回頭在看那個存儲著mmmm.py文件的目錄中(關(guān)于mmmm.py文件可...
摘要:本文重點了解數(shù)據(jù)模型和接口的概念掌握特殊方法的定義,作用和基本用法。一基本概念數(shù)據(jù)模型是數(shù)據(jù)特征的抽象,這里是對框架的描述。數(shù)據(jù)模型規(guī)范了自身構(gòu)建模塊的接口,模塊包括但不限于序列迭代器函數(shù)類和上下文管理器。 導語:本文章記錄了本人在學習Python基礎之緒論篇的重點知識及個人心得,以加深自己的理解。 本文重點: 1、了解Python數(shù)據(jù)模型和接口的概念;2、掌握特殊方法的定義,作用和基...
摘要:函數(shù)的基本結(jié)構(gòu)中的函數(shù)基本結(jié)構(gòu)函數(shù)名參數(shù)列表語句幾點說明函數(shù)名的命名規(guī)則要符合中的命名要求。在中,將這種依賴關(guān)系,稱之為多態(tài)。不要期待在原處修改的函數(shù)會返回結(jié)果比如一定要之用括號調(diào)用函數(shù)不要在導入和重載中使用擴展名或路徑。 在本教程的開始部分,就已經(jīng)引入了函數(shù)的概念:《永遠強大的函數(shù)》,之所以那時候就提到函數(shù),是因為我覺得函數(shù)之重要,遠遠超過一般。這里,重回函數(shù),一是復習,二是要在已經(jīng)...
閱讀 1685·2019-08-30 15:54
閱讀 2448·2019-08-30 15:52
閱讀 2172·2019-08-29 15:33
閱讀 3094·2019-08-28 17:56
閱讀 3296·2019-08-26 13:54
閱讀 1729·2019-08-26 12:16
閱讀 2509·2019-08-26 11:51
閱讀 1719·2019-08-26 10:26