python魔法方法-屬性轉換和類的表示,python魔法
類型轉換魔法
類型轉換魔法其實就是實現了str、int等工廠函數的結果,通常這些函數還有類型轉換的功能,下面是一些相關的魔法方法:
__int__(self)
轉換成整型,對應int函數。
__long__(self)
轉換成長整型,對應long函數。
__float__(self)
轉換成浮點型,對應float函數。
__complex__(self)
轉換成 複數型,對應complex函數。
__oct__(self)
轉換成八進位,對應oct函數。
__hex__(self)
轉換成十六進位,對應hex函數。
__index__(self)
首先,這個方法應該返回一個整數,可以是int或者long。這個方法在兩個地方有效,首先是 operator 模組中的index函數得到的值就是這個方法的傳回值,其次是用於切片操作,下面會專門進行代碼示範。
__trunc__(self)
當 math.trunc(self) 使用時被調用.__trunc__返回自身類型的整型截取 (通常是一個長整型).
__coerce__(self, other)
實現了類型的強制轉換,這個方法對應於 coerce 內建函數的結果(python3.0開始去掉了此函數,也就是該魔法方法也沒意義了,至於後續的版本是否重新加入支援,要視官方而定。)
- 這個函數的作用是強制性地將兩個不同的數字類型轉換成為同一個類型,例如:
#coerce(x, y) -> (x1, y1)
方法返回一個元祖,分別對應轉換後的兩個數字。其優先順序為:複數>浮點數>長整型>整型。在轉換的時候,會轉換為兩個參數中優先順序高的類型。當轉換無法完成的時候,會觸發 TypeError。
而當我們定義這個魔法方法時,如果轉換無法完成,應該返回None。
這裡有個重要的機制,當python進行運算的時候,如 1 + 1.0 時,會先調用 coerce 函數將其轉換為同一個類型,然後再進行運行,這也就是為什麼 1 + 1.0 = 2.0,因為轉換之後實際進行的運算為 1.0 +1.0。得到這樣的結果也就不奇怪了。
程式碼範例:
class Foo(object): def __init__(self, x): self.x = x def __int__(self): return int(self.x) + 1 def __long__(self): return long(self.x) + 1a = Foo(123)print int(a)print long(a)print type(int(a))print type(long(a))
這裡要注意一點,魔法方法的傳回值必須符合預期,例如 __int__ 就應該返回一個 int 類型,如果我們任性地返回其他類型,例如字串(str)、列表(list)等,會報錯。
def __int__(self): return str(self.x)
def __int__(self): return list(self.x)
但是 int 可以返回 long,而 long 返回 int 時會自動被處理成 long:
class Foo(object): def __init__(self, x): self.x = x def __int__(self): return long(self.x) + 1 def __long__(self): return int(self.x) + 1a = Foo(123)print int(a)print long(a)print type(int(a))print type(long(a))
以上發生在python2.7.11上,這是一個很奇怪的行為,以至於我認為其可能是一個 BUG,總之我們在使用的時候要注意要返回對應的類型就是了,以免出錯。
__index__(self):
首先是對應於operator.index(),operator.index(a)就相當於a.__index__():
import operatorclass Foo(object): def __init__(self, x): self.x = x def __index__(self): return self.x + 1a = Foo(10)print operator.index(a)
另一個是很神奇的特效,當其用於序列中時:
class Foo(object): def __init__(self, x): self.x = x def __index__(self): return 3a = Foo('scolia')b = [1, 2, 3, 4, 5]print b[a]print b[3]
可以作為索引一樣使用,可進行切片操作:
class Foo(object): def __init__(self, x): self.x = x def __index__(self): return int(self.x)a = Foo('1')b = Foo('3')c = [1, 2, 3, 4, 5]print c[a:b]
其實切片內部使用的函數 slice 對其進行了處理,有興趣的同學可以去瞭解這個函數:
a = Foo('1')b = Foo('3')c = slice(a, b)print cd = [1, 2, 3, 4, 5]print d[c]
__coerce__(self, other):
程式碼範例:
class Foo(object): def __init__(self, x): self.x = x def __coerce__(self, other): return self.x, str(other.x)class Boo(object): def __init__(self, x): self.x = x def __coerce__(self, other): return self.x, int(other.x)a = Foo('123')b = Boo(123)print coerce(a, b)print coerce(b, a)
總結:是調用了第一個參數的魔法方法。
類的表示 :
類的表示其實就是對外的特徵,例如使用print語句時,列印出來的是什麼,其實本質上也是對應函數的輸出:
__format__(self, formatstr)
定義當你的一個類的執行個體被用來用新式的格式化字串方法進行格式化時所要產生的行為。例如, "Hello, {0:abc}!".format(a) 將會導致調用 a.__format__("abc") 。這對定義你自己的數值或字串類型
是十分有意義的,你可能會給出一些特殊的格式化選項。
這裡並沒有什麼特別難以理解的地方,所以代碼例子就略去了。
歡迎大家交流。