Python Built-in Class Attributes、魔術方法 詳解

魔術方法

基本定製

說明

C.__init__(self[, arg1, ...]) 構造器(帶一些可選的參數)
C.__new__(self[, arg1, ...]) 構造器(帶一些可選的參數);通常用在設置不變數據類型的子類
C.__del__(self) 解構器
C.__str__(self) 可打印的字符輸出;內建str()及print 語句
C.__repr__(self) 運行時的字符串輸出;內建repr()  ‘‘  和 操作符
C.__unicode__(self)b Unicode 字符串輸出;內建unicode()
C.__call__(self, *args) 表示可調用的實例
C.__nonzero__(self) 爲object 定義False 值;內建bool() (從2.2 版開始)
C.__len__(self) “ ” 長度(可用於類);內建len()

示例

class A():
    def __init__(self):
        print "call __init__"
        self.a = 1

    def __new__(self):
        print "call __new__"

    def __del__(self):
        print "call __del__"

    def __str__(self):
        print "call __str__"
        return "class A str"

    def __repr__(self):
        print "call __repr__"
        return "class A repr"

    def __unicode__(self):
        print "call __unicode__"
        return "class A unicode"

    def __nozero__(self):
        print "call __nozero__"
        return 1

    def __len__(self):
        print "call __len__"
        return 1
    #定以後callable(instance) True
    def __call__(self, *args):
        print "call __call__"
a = A()
print a
repr(a)
unicode(a)
print bool(a)
print len(a)
print callable(a)

A.new和init區別

class A(object):
    def __init__(self):
        print "call __init__"
        self.value = 1

    def __new__(cls):
        print "call __new__"
        return super(A, cls).__new__(cls)

a = A()
print a.value

__new__:創建對象時調用,返回當前對象的一個實例,相當於java裏面的構造器 一般是用於繼承內置類的,返回值是一個對象

使用:需要控制一個新實例的創建,一般情況下不會使用,除非需要子類化不可變類型例如str/int/unicode/tuple

__init__:創建完對象後調用,對當前對象的實例的一些初始化,無返回值

使用:需要控制一個實例的初始化

可以這樣理解,默認是創建(new),然後調用__init__ (new的時候,self還不存在, init的時候self已經存在了)

對象值比較

說明

C.__cmp__(self, obj) 對象比較;內建cmp()
C.__lt__(self, obj) and 小於/小於或等於;對應<及<=操作符
C.__le__(self,obj)
C.__gt__(self, obj) and 大於/大於或等於;對應>及>=操作符
C.__ge__(self,obj)
C.__eq__(self, obj) and 等於/不等於;對應==,!=及<>操作符
C.__ne__(self,obj)

示例

class A():
    def __init__(self, value):
        self.value = value

    def __cmp__(self, obj):
        print "call __cmp__"
        return self.value - obj.value

    def __lt__(self, obj):
        print "call __lt__"
        return self.value < obj.value

    def __gt__(self, obj):
        print "call __gt__"
        return self.value > obj.value

    def __eq__(self, obj):
        print "call __eq__"
        return self.value == obj.value

a1 = A(1)
a2 = A(2)
print cmp(a1,a2)
print a1 < a2
print a1 > a2
print a1 == a2

屬性操作

說明:

C.__getattr__(self, attr) 獲取屬性;內建getattr();僅當屬性沒有找到時調用
C.__setattr__(self, attr, val) 設置屬性
C.__delattr__(self, attr) 刪除屬性
C.__getattribute__(self, attr) 獲取屬性;內建getattr();總是被調用
C.__get__(self, attr) (描述符)獲取屬性
C.__set__(self, attr, val)  (描述符)設置屬性
C.__delete__(self, attr)  (描述符)刪除屬性

示例

class A():
    def __init__(self):
        self.value = 1
    def __getattr__(self, name):
        print "call __getattr__"
        try:
            return self.__dict__[name]
        except:
            return "not found"

    def __setattr__(self, name, value):
        print "call __setattr__"
        self.__dict__[name] = value

    def __delattr__(self, name):
        print "call __delattr__"
        del self.__dict__[name]

    def __getattribute__(self, name):
        print "call __getattribute__"
        return self.__dict__[name]

    def __get__(self, name):
        pass
    def __set__(self, name, value):
        pass
    def __del__(self):
        pass

a = A()
print getattr(a, "value")
print getattr(a, "name")
del a.value

A.get/getattr/getattribute區別

object.getattr(self, name)

當一般位置找不到attribute的時候,會調用getattr,返回一個值或AttributeError異常。

object.getattribute(self, name)

無條件被調用,通過實例訪問屬性。如果class中定義了__getattr__(),則__getattr__()不會被調用(除非顯示調用或引發AttributeError異常)

object.get(self, instance, owner)

如果class定義了它,則這個class就可以稱爲descriptor。owner是所有者的類,instance是訪問descriptor的實例,如果不是通過實例訪問,而是通過類訪問的話,instance則爲None。(descriptor的實例自己訪問自己是不會觸發__get__,而會觸發__call__,只有descriptor作爲其它類的屬性纔有意義。)

數值及二進制

二元

C.__*add__(self, obj) 加;+操作符
C.__*sub__(self, obj) 減;-操作符
C.__*mul__(self, obj) 乘;*操作符
C.__*div__(self, obj) 除;/操作符
C.__*truediv__(self, obj)  True 除;/操作符
C.__*floordiv__(self, obj)  Floor 除;//操作符
C.__*mod__(self, obj) 取模/取餘;%操作符
C.__*divmod__(self, obj) 除和取模;內建divmod()
C.__*pow__(self, obj[, mod]) 乘冪;內建pow();**操作符
C.__*lshift__(self, obj) 左移位;<<操作符

二進制

C.__*rshift__(self, obj) 右移;>>操作符
C.__*and__(self, obj) 按位與;&操作符
C.__*or__(self, obj) 按位或;|操作符
C.__*xor__(self, obj) 按位與或;^操作符

一元

C.__neg__(self) 一元負
C.__pos__(self) 一元正
C.__abs__(self) 絕對值;內建abs()
C.__invert__(self) 按位求反;~操作符

數值轉換

C.__complex__(self, com) 轉爲complex(複數);內建complex()
C.__int__(self) 轉爲int;內建int()
C.__long__(self) 轉爲long;內建long()
C.__float__(self) 轉爲float;內建float()

其他

C.__oct__(self) 八進制表示;內建oct()
C.__hex__(self) 十六進制表示;內建hex()
C.__coerce__(self, num) 壓縮成同樣的數值類型;內建coerce()
C.__index__(self)g 在有必要時,壓縮可選的數值類型爲整型(比如:用於切片索引等等

序列

說明

C.__len__(self) 序列中項的數目
C.__getitem__(self, ind) 得到單個序列元素
C.__setitem__(self, ind,val) 設置單個序列元素
C.__delitem__(self, ind) 刪除單個序列元素

C.__getslice__(self, ind1,ind2) 得到序列片斷
C.__setslice__(self, i1, i2,val) 設置序列片斷
C.__delslice__(self, ind1,ind2) 刪除序列片斷
C.__contains__(self, val) f 測試序列成員;內建in 關鍵字
C.__*add__(self,obj) 串連;+操作符
C.__*mul__(self,obj) 重複;*操作符
C.__iter__(self)  創建迭代類;內建iter()

示例

class A():
    def __init__(self):
        print "call __init__"
        self.value = [1,2,3,4,5,6]

    def __len__(self):
        print "call __len__"
        return len(self.value)

    def __getitem__(self, index):
        print "call __getitem__"
        return self.value[index]

    def __setitem__(self, index, value):
        print "call __setitem__"
        self.value[index] = value

    def __delitem__(self, index):
        print "call __delitem__"
        del self.value[index]

a = A()
print len(a)
print a[2]
a[2] = 99
del a[2]

映射

C.__len__(self) mapping 中的項的數目
C.__hash__(self) 散列(hash)函數值
C.__getitem__(self,key) 得到給定鍵(key)的值
C.__setitem__(self,key,val) 設置給定鍵(key)的值
C.__delitem__(self,key) 刪除給定鍵(key)的值
C.__missing__(self,key) 給定鍵如果不存在字典中,則提供一個默認值


內置類變量

這期的話題有點簡單, 整理下常見的模塊內置方法

剛開始學Python的時候, 看到if __name__ == '__main__': main()就不明覺厲了, 一直好奇__name__這貨到底是個什麼東東

實際上, __name__是Python中模塊的內置屬性, 除此之外, 經常用到的還有__file____doc____all____package__等等

__name__

__name__是模塊內置的一個屬性, 一般如果模塊是被引用的時候, 它的值是模塊名, 如果這個python文件被直接運行, 那麼它的值是'__main__'

>>> __name__
'__main__'
>>> import os
>>> os.__name__
'os'

所以我們寫一個腳本的時候,通過判斷__name__來確定腳本是被引用, 還是被直接運行

if __name__ == `__main__`:
    main()

__file__

被引用模塊文件的路徑

>>> import os
>>> os.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'

__doc__

模塊的註釋文檔

class MyClass:
    """這是MyClass的註釋, 
    調用下面myClass.__doc__的時候會返回這段內容"""

    def funcA(self):
        """這是funcA的註釋文檔"""
        return "hello"

myClass = MyClass()

調用myClass.__doc__會返回MyClass的註釋文檔, myClass.funcA.__doc__會返回funcA的註釋文檔

如果執行help(MyClass), 所看到的文檔實際就是DocStrings收集該類下所有的註釋生成的文檔

__all__

當你寫一個Python的模塊的時候, 一般在__init__.py中指定__all__來表示當這個模塊被import * from xxx的時候, 有哪些模塊會被import進來,

當然, 我們推薦儘量不使用import *

__package__

__package__主要是爲了相對引用而設置的一個屬性, 如果所在的文件是一個package的話, 它和__name__的值是一樣的, 如果是子模塊的話, 它的值就跟父模塊一致

比如 modA/modB/aa.py__name__的值是modA.modB.aa __package__modA.modB
modA/modB/__init__.py__name____package__的值都是modA.modB


如何查看內建方法和變量的文檔

>>>print dir(an_object_name)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribut
e__', '__getitem__', '__getslice__', '__hash__', '__init__', '__new__', '__reduc
e__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__',

'__str__', '__subclasshook__', '__unicode__', 'args', 'message']

然後使用help(***)來查詢文檔信息




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章