1. 程式人生 > >python類:magic魔術方法

python類:magic魔術方法

魔術方法是面向物件Python語言中的一切。它們是你可以自定義並新增“魔法”到類中的特殊方法。它們被雙下劃線環繞(比如__init__或__lt__)。

在Python中,我們可以通過”魔術方法”使自定義的class變得強大、易用。例如當我們想定義一個可迭代的類物件的時候,就可以去實現”__iter__(self)”這個魔術方法;

構造與初始化

我們每個知道的最基本的“魔法”方法是__init__。一種讓我們在初始化一個類時定義一些行為。然而當我執行 x = SomeClass(), __init__ 不是第一個被執行的。事實上,第一被執行的的方法是__new__,它會建立一個例項,然後在構造器建立時傳遞一些引數。在一個object的生命週期的另一端的方法是__del__。讓我們仔細看看這3個“魔法”方法:

  • __new__(cls, [...)
  • __new__ 是一個類的初始化過程中第一個被執行的方法。它建立了類,然後把一些引數傳遞給__init__。__new__ 很少被使用,特別是當我們用一些不可變型別的子類時(像tuple ,string),我不想關心__new__的太多的細節,因為那是沒有用的。但它有它存在的意義。更多詳細的請看 in the Python docs.
  • __init__(self, [...)
  • 類的構造器,當初始構造方法被執行(例如,我們執行 x = SomeClass(10,'foo')),__init__ 就會獲得 10 和 ‘foo’ 作為引數。__init__ 在python類的定義中經常被使用
  • __del__(self)
  • 如果 __new__ 和 __init__ 形成一個類的建構函式,__del__ 是就是解構函式。它不實現語句 del x 的行為(這樣程式碼就不會轉換為 x.__del__())。它定義了一個被垃圾回收的行為。它在類消除的時後需要做一些額外的行為時是非常有用的,就像 sockets 和 file 類。注意,當編譯器還在執行,如果類還存活著,這裡不能確保__del__一定會被執行。所以__del__ 不能替代一些良好的程式設計習慣(比如連線用完了將其關掉),事實上__del__很少被使用,因為它的呼叫是非常不穩定的;請謹慎使用!

把他們合起來後,這裡就是一個 __init__ 和 __del__ 使用的例子:

Python
12345678910fromos.pathimportjoinclass FileObject:'''Wrapper for file objects to make sure the file gets closed on deletion.'''def__init__(self,filepath='~',filename='sample.txt'):# open a file filename in filepath in read and write modeself.file=open(join(filepath,filename),'r+')def__del__(self):self.file.close()delself.file

自定義類操作

我們使用Python的“魔法”方法最大得優勢之一是它提供了一種簡單的方法去定義類的行為,比如 built-in 型別。這就意味著你可以避免醜陋的,違反直覺的,非標準化的基本操作方法。在一些語言中,他們通常這樣寫:

Python
12ifinstance.equals(other_instance):# do something

但是這增加了混亂和不必要的冗餘。不同的類庫中的相同的方法可能會用不同名字,使得使用者做了太多不必要的操作。相比之下“魔法”方法是強大的,我們可以使用它定義一個方法代替上面的例子(__eq__ , 在這個例子中):

Python
12ifinstance==other_instance:#do something

這是“魔法”方法強大用途的一部分。他們絕大部分讓我們定義操作的意義,以至於我們可以使用他們在我們自己的類中就像使用built in 型別。

魔法比較方法

python擁有大量用於實現物件與物件之間比較的魔法方法,這些物件使用運算子進行直觀比較而不是難看的方法呼叫。同時它也提供了一種方法去過載python預設的物件比較行為(比較引用)。這裡有一個這些方法和它們做了什麼事情的列表:

  • __cmp__(self, other)
  • __cmp__ 是比較方法裡面最基本的的魔法方法。實際上它實現了所有的比較運算子(如<, ==, !=)的行為,但也許不是你想要的行為(例如,一個例項是否和另一個例項相等應該由某個條件來決定,一個例項是否大於另一個例項應該由其他的條件來決定)。當self < other時__cmp__應該返回一個負整數,當self == other時返回0,self > other時返回正整數。通常來說最好是定義每個你需要的比較方法而不是一次性定義所有的比較方法,但是__cmp__是一個消除重複性的良途,並且當你有很多比較方法需要用相類似的條件去實現的時候這能讓程式碼變得清晰。
  • __eq__(self, other)
  • 定義相等符號的行為,==
  • __ne__(self,other)
  • 定義不等符號的行為,!=
  • __lt__(self,other)
  • 定義小於符號的行為,<
  • __gt__(self,other)
  • 定義大於符號的行為,>
  • __le__(self,other)
  • 定義小於等於符號的行為,<=
  • __ge__(self,other)
  • 定義大於等於符號的行為,>=

例如,假設一個類是一個單詞模型。我們可能要按字典比較單詞(按字母),這是比較字串預設行為,但我們也可能需要基於其他一些標準來做比較,比如按長度、或位元組數量等。在下面的例子中,我們將比較長度。下面是實現:

Python
12345678910111213141516171819classWord(str):'''Class for words, defining comparison based on word length.'''def__new__(cls,word):# Note that we have to use __new__. This is because str is an immutable# type, so we have to initialize it early (at creation)if' 'inword:print"Value contains spaces. Truncating to first space."word=word[:word.index(' ')]# Word is now all chars before first spacereturnstr.__new__(cls,word)def__gt__(self,other):returnlen(self)>len(other)def__lt__(self,other):returnlen(self)<len(other)def__ge__(self,other):returnlen(self)>=len(other)def__le__(self,other):returnlen(self)<=len(other)

現在,我們可以建立兩個單詞(通過使用Word(‘foo’)和Word(‘bar’))然後依據長度比較它們。但要注意,我們沒有定義__eq__和__ne__,因為這樣會導致其他一些奇怪的行為(尤其是Word(‘foo’)==Word(‘bar’)會判定為true),它不是基於長度相等意義上的測量,所以我們迴歸到字元平等意義上的實現。

現在需要留心啦——為達到預期的比較效果你不需要為每個比較定義魔術方法。如果你只定義__eq__以及其他的(比如__gt__,__lt__等),標準庫已經在functools模組裡為我們提供了一個類修飾器,它可以定義所有的富特性比較方法。這個特性只有在Python 2.7中才是可用的,但如果你碰巧的話這可以節省大量的時間和精力。你可以通過將@total_ordering放置在類定義前面來使用它。

數值魔術方法

就如同你可以通過定義比較操作來比較你自己的類例項一樣,你也可以自己定義數學運算子號的行為。好吧,先繫緊你的褲腰帶,深呼吸……,這些操作可多著呢。由於文章組織需要,我把這些數學“魔術方法”分為5類:單目運算操作,一般數學運算操作,滿足交換律的數學運算(後面會有更多介紹),引數賦值操作和型別轉換操作:

單目運算子操作與函式:

單目運算子或單目運算函式只有一個運算元: 比如取負(-2),絕對值操作等。

  • __pos__(self)
  • 實現一個取正數的操作(比如 +some_object ,python呼叫__pos__函式)
  • __neg__(self)
  • 實現一個取負數的操作(比如 -some_object )
  • __abs__(self)
  • 實現一個內建的abs()函式的行為
  • __invert__(self)
  • __round__(self, n)
  • 實現一個內建的round()函式的行為。 n 是待取整的十進位制數.
  • __floor__(self)
  • 實現math.floor()的函式行為,比如, 把數字下取整到最近的整數.
  • __ceil__(self)
  • 實現math.ceil()的函式行為,比如, 把數字上取整到最近的整數.
  • __trunc__(self)
  • 實現math.trunc()的函式行為,比如, 把數字截斷而得到整數.
  • 一般算數運算

    好吧,現在我們開始介紹雙目運算操作或函式,比如 +, -, * 等等. 這些很容易自解釋.

    • __add__(self, other)
    • 實現一個加法.
    • __sub__(self, other)
    • 實現一個減法.
    • __mul__(self, other)
    • 實現一個乘法.
    • __floordiv__(self, other)
    • 實現一個“//”操作符產生的整除操作()
    • __div__(self, other)
    • 實現一個“/”操作符代表的除法操作.
    • __truediv__(self, other)
    • 實現真實除法,注意,只有當你from __future__ import division時才會有效
    • __mod__(self, other)實現一個“%”操作符代表的取模操作.
    • __divmod__(self, other)
    • 實現一個內建函式divmod()
    • __pow__
    • 實現一個指數操作(“**”操作符)的行為
    • __lshift__(self, other)
    • 實現一個位左移操作(<<)的功能
    • __rshift__(self, other)
    • 實現一個位右移操作(>>)的功能.
    • __and__(self, other)
    • 實現一個按位進行與操作(&)的行為.
    • __or__(self, other)實現一個按位進行或操作(|)的行為.
    • __xor__(self, other)
    • 實現一個異或操作(^)的行為

反射算術運算子

你相信我說我能用一位來表示反射運算嗎?可能有人會認為表示一個反射運算是大的嚇人的“外國概念”,反射實際上它是非常簡單的。看下面的例子:

Python
1

相關推薦

pythonmagic魔術方法

魔術方法是面向物件Python語言中的一切。它們是你可以自定義並新增“魔法”到類中的特殊方法。它們被雙下劃線環繞(比如__init__或__lt__)。在Python中,我們可以通過”魔術方法”使自定義的class變得強大、易用。例如當我們想定義一個可迭代的類物件的時候,就可

Python常用的魔術方法

類的常用魔術方法:無需人為呼叫,基本是在特定的時刻自動觸發,方法名被前後兩個下劃線包裹 __init__:建構函式。 __new__:物件例項化方法,其實這才是類裡面第一個被呼叫的方法,在建構函式之前呼叫,之後才是__init__,只是這個比較特殊,一般不使用。 __call__:物件當

Python面向對象4的常用魔術方法

一個 操作 delet 不存在 兩個 strong 參數 否則 成員 魔術方法就是不需要人為調用的方法,基本是在特定的時刻自動觸發- 魔術方法的統一的特征,方法名被前後各兩個下滑線包裹- 操作類 - `__init__`: 構造函數 - `__new__`: 對

Python和實例方法和屬性的動態綁定

tuple attribute 名稱 one 運行 作用 span people tee python中實例創建後可以給實例綁定任何屬性和方法 class Student(object): pass   給實例綁定一個屬性: s=Student() s.n

python面向對象魔術方法補充

返回結果 isp src 通過 存在 xxxxx eight span lap 一、描述符   在 面向對象 編程中 定義一個(沒有定義方法)類:class person , 在這個類裏面,有name,age, heigth, weight,等等屬性, 這個類就可以看作一

python的屬性和方法總結

python一、類的屬性總結(類的屬性定義在方法外,對象的屬性定義在方法內)理解:類的(靜態)屬性:(人類的五官,理解為變量)類的(動態)方法:(人類吃穿住行,理解為一個函數,至少帶一個參數self,指向類本身)對象:類的實例化,之後才能有屬性和方法1)類的屬性,也是公有屬性;類的私有屬性2)對象的公有屬性;

Python的繼承和方法重寫總結

python 類繼承和重寫 Python類的繼承和方法重寫總結 我們都知道類可以繼承,通過繼承可以實現代碼的復用,使代碼看起來更加簡潔 比如:Class B(A): Pass 定義了一個名為B的類,它繼承於A,我們把B叫做A的子類,A叫做B的超類(父類)。 方法重寫當子類定義了一個和超類相同名字的方

Python 的特殊成員方法

img 解釋 字典 基類 技術 pos call () log 類的特殊成員方法 1.__doc__ :打印類的描述信息 class Foo: """ 描述類信息,這是用於看片的神奇 """ def func(self): pass p

Python面向對象-魔術方法

錯誤 名稱 args exception 引入 per ttr 用處 dir() 實例化相關 對象的實例化過程如下所示: 示例: class Programer(): def __new__(cls,*args,**kwargs): print(&

Python的內置方法

app war 語句塊 輸入 查看 註意 構造 重寫 print 目錄 1、new、init 2、str、repr 3、call 4、del 5、iter、next 6、getitem、setitem、delitem 7、getattr、setattr、delattr 8

Python-的繫結方法與非繫結方法

類中定義的函式分成兩大類 一:繫結方法(繫結給誰,誰來呼叫就自動將它本身當作第一個引數傳入): 繫結到類的方法:用classmethod裝飾器裝飾的方法。 為類量身定製 類.boud_method(),自動將類當作第一個引數傳入 (其實物件也可呼叫,但仍將類當作第一個

python中三種類方法區別

python類裡會出現這三個單詞,self和cls都可以用別的單詞代替,類的方法有三種, 一是通過def定義的 普通的一般的,需要至少傳遞一個引數,一般用self,這樣的方法必須通過一個類的例項去訪問,類似於c++中通過物件去訪問; 二是在def前面加上@classmethod,這種類方法的

Python及常見的方法屬性定義

Python類及常見的方法屬性定義 Python是一門完全面向物件(OOP)的語言,對於Python來說,一切皆物件,   一切皆物件, 貓,老虎,狗,狼這些都是我們認識的一種動物,在現實生活中我們把它叫做動物,而在面向物件的程式語言(OOP)中我們稱這類在生活中的具體事物叫做物件

python -- 中--內置方法

神奇 args __str__ 否則 打印 iss sch __call__ als isinstance 和 issubclass isinstance(obj,b) 檢查是否obj是否是類b的對象 class A(object):pass class B(

Python筆記字串常用方法大全,手慢無(收藏專用)

文章目錄 字串大小寫轉換 字串格式輸出 字串搜尋定位與替換 字串的聯合與分割 字串條件判斷 字串切片大全 實戰示例 一、字串大小寫轉換 二、字串輸出 三、字串搜尋定位與替換 四、字串的聯合與分割

python中的私有方法

假設有如下一個python類: class Foo(object): def __a(self): print "Bet you can't see me..." def bar(self):        &nbs

python中兩個魔術方法 __repr__和__str__

repr() 和 str() 的區別 str() 1 使用str()函式時, 才呼叫__str_ __ 2 使用print()函式時 3 str() 的輸出追求可讀性,輸出格式要便於理解,適合用於輸出內容到使用者終端。 repr() 1 使用repr()時,才呼叫___re

python面向物件、繼承、slot、多重繼承

python面向物件基礎知識面向物件的三大特性:封裝、繼承和多型。繼承在Python中,同時支援單繼承與多繼承,一般語法如下:class SubClassName(ParentClass1 [, ParentClass2, ...]):    class_suite繼承示例1

Python入門os部分方法介紹(一)

>>> help(os) Help on module os: NAME os - OS routines for Mac, NT, or Posix depending on what system we’re on.

python的三種方法

python類有三種方法。 1.一般方法,即不加任何修飾的,直接用def定義的方法。如: In [14]: class A: ...: def a(self): ...: print('一般方法') ...