1. 程式人生 > >chapter9.1、魔術方法

chapter9.1、魔術方法

魔術方法

python精華之一

特殊屬性

__name__ 類,函式,方法等的名字
__modle__ 主模組,當前的模組__main__,其他模組呼叫返回模組物件
__class__ 相當於type,物件或類所屬的類
__bases__ 返回基類的元組,順序為基類列表中出現的順序
__doc__ 文件,未定義為None
__mro__ 類的mro,定義時就會計算並放在類的屬性裡的__mro__中
__dict__ 類或例項的屬性,可寫的字典,這裡注意有些只讀字典

檢視屬性

__dir__ 返回類的或者物件的所有成員的列表,

dir()函式呼叫__dir__(),dir是內建函式,

如果類中和例項中定義了__dir__:

  使用例項呼叫時,例項中如果定義了__dir__,就會覆蓋類__dir__,返回例項中的__dir__的執行結果;

  如果例項中沒有,就會呼叫父類的,如果父類沒有,就繼續向上找,中間有的話就會執行該方法;

如果類中和例項中沒有定義__dir__:

  如果物件是模組物件,返回的列表包含檔案的屬性名和變數名,受作用域影響,一般在模組上使用時,呼叫模組,在自己的模組蒐集

  如果物件是類或類的例項,近似於自己例項的字典加類的字典加object的字典,返回列表包含類的屬性名,及它的基類的屬性名

  如果dir()    括號中不寫,返回的列表包含不同的內容

    在模組中,返回模組的屬性和變數名

    在函式中,返回本地作用域的變數名

    在函式中,返回本地作用域的變數名

 

魔術方法 

建立,初始化與銷燬

    __new__ 例項化,可以不寫,會去調父類的方法。一定要return,返回不要再調自己,調本型別的例項,如果不是cls的例項,就不會呼叫__init__,即使建立了該方法,也會使用return super().__new__(cls), 最後呼叫的是object的__new__方法建立並返回例項

    __init__

    __del__
__hash__  內建函式hash()呼叫後的返回值,返回整數,現在Linux的加密主要使用的MD5演算法也是hash演算法的一種,

  雜湊演算法,具有冪等性,同一個程式中不論計算多少次,相同的物件返回的hash的值都一樣,

  不同的hash演算法,可能會產生hash衝突,不同的x可能求得同樣的值

__eq__ 判斷是否相同,返回一個bool值,hash函式只負責計算hash,去重需要__eq__判斷,

  一般hash只要不衝突,就不會呼叫__eq__,__eq__ 對應  '=='  操作符,判斷兩個物件是否相等,返回bool。

  一旦類中提供__eq__ ,類中就會自動新增__hash__=None

  hash值相等不代表物件相等,

  list類的例項不可hash,在list類中,原始碼中有__hash__ = None,也就是說如果呼叫__hash__相當於呼叫None,

  如果你建立的類不能被hash,那就把__hash__設定為None

import math

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def  __hash__(self):
        return  hash((self.x, self.y))

    def __eq__(self, obj):
        return self.x == obj.x and self.y == obj.y

p1 = Point(3, 0)
p2 = Point(0, 4)
p3 = Point(3, 0)
print({p1, p2, p3})##可以去重

 

__bool__    內建函式bool(),或者物件放在邏輯表示式的位置,呼叫這個函式返回布林值

  沒有定義__bool__()的,就去__len__()返回長度,非零為真

視覺化方法

__repr__ 內建函式repr()對一個物件獲取字串表達,

  呼叫__repr__方法返回字串,間接呼叫會調,如果未定義,直接返回object的定義,也就是顯示記憶體地址的資訊

__str__ 例項直接print(),或者str(),或者format(),呼叫時,要返回物件的字串表達,

  如果沒有定義,就去呼叫__repr__方法返回字串表示式,如果沒有__repr__定義,就直接返回物件的記憶體地址

  類不提供__str__,就使用__repr__;不提供__repr__就去object找,

  要注意:列印物件,輸出形式,打印出來的型別不作數,並不能真正的表達物件的型別!

__bytes__ 提供bytes方法,bytes()函式呼叫,返回一個物件的bytes表達,即返回bytes物件

 

運算子過載

<  __lt__    小於    lessthan

<=  __le__    小於等於    lessequal

>  __gt__    大於    greatthan 

>=  __ge__    大於等於    greatequal

==  __eq__    等於    equal   ,只有==才呼叫

!=  __ne__  不等於    notequal

+ - * /  __add__ ,__sub__ ,__mul__ ,__truediv__ 加減乘除過載

%  __mod__  取模運算過載

//  __floordiv__  整除過載

**  __pow__  乘方過載

divmod  __divmod__        取模取餘

+= ,-= , *= , /= , %= , //= , **=    __iadd__ , __isub__ , __imul__ , itruediv__ , __imod__ , __ifloordiv__ , __ipow__   ,其中的 i 表示in place,立即返回

如果不定義加等,就去調add,在賦值給左邊的值,其他的運算也是

例項之間的計算,可以用座標點來理解

import math
class
Point: def __init__(self,x,y): self.x = x self.y = y def __eq__(self,obj): return self.x ==obj.x and self.y == obj.y def __add__(self,other): return Point(self.x + other.x,self.y+other.y) def __sub__(self,other): return Point(self.x - other.x,self.y-other.y) def __repr__(self): return "({},{})".format(self.x,self.y)

 

還可以使用total ordering 模組,但是要提供等於和大小與四種之中的一種,一般自己寫,寫三個,等於,大小於中的一個,和大於小於中的一個,就可以推斷另一個

大於推斷小於

等於推斷不等於

大於等於推斷小於等於

 用total ordering 可能產生效能問題,儘量自己寫,

類的大量運算,運算子是較常見的表達方式,提供運算子過載比提供加法方式更符合使用者的習慣

可參見int的所有的操作符,幾乎實現了所有的操作符

容器相關方法

__len__  內建函式len(),返回物件的長度(>=0),將物件看作容器,bool()函式呼叫時,沒有__bool__屬性時,就會來判斷__len__是否存在,如果存在且不為0,就返回真

__iter__  迭代容器內容時,返回一個迭代器物件

__contains__  in成員運算子,沒有實現,就調__iter__遍歷,查詢都要遍歷,可以不寫contains

__getitem__  實現self [ key ] 訪問,如果是序列物件,key就是整數索引,或者是切片,對於字典和集合,key是hashable的,不存在就KeyError

__setitem__  和getitem訪問類似,是設定值的方法

__missing__  字典和類使用時,__getitem__()呼叫key不存在時執行