概念解析
魔法方法是python的一種高級(jí)語(yǔ)法布持,他們是可以給你的類增加“magic”的特殊方法洗做,比如:增加一些額外的功能驯嘱。函數(shù)格式為_(kāi) xx _(被雙下劃線包圍的函數(shù))灶壶。
魔法方法
- 基本定制
object.__init__(self, *args, **kwargs) # 構(gòu)造器义郑,創(chuàng)建完對(duì)象后調(diào)用蝶柿,進(jìn)行當(dāng)前實(shí)例的初始化
object.__new__(cls, *args, **kwargs) # 構(gòu)造器,創(chuàng)建對(duì)象時(shí)調(diào)用非驮,返回值是一個(gè)對(duì)象
object.__del__(self) # 解構(gòu)器交汤,刪除對(duì)象時(shí)調(diào)用
object.__str__(self) # 若類C中實(shí)現(xiàn)此方法,當(dāng)str(C())時(shí)此方法被調(diào)用
object.__len__(self) # 若類C中實(shí)現(xiàn)此方法劫笙,當(dāng)len(C())時(shí)此方法被調(diào)用
測(cè)試代碼如下:
# coding=utf-8
class MagicDemo(object):
def __init__(self):
"""對(duì)當(dāng)前對(duì)象的實(shí)例的一些初始化"""
print "call me second"
self.value = [1, 2, 3]
def __new__(cls, *args, **kwargs):
"""
真正的構(gòu)造函數(shù)芙扎,先于__init__調(diào)用,
返回創(chuàng)建的對(duì)象
"""
print "call me first"
return super(MagicDemo, cls).__new__(cls, *args, **kwargs)
def __del__(self):
print "call __del__"
del self
def __len__(self):
print "call __len__"
return len(self.value)
def __str__(self):
return "call __str__"
if __name__ == '__main__':
mag = MagicDemo()
print mag.value
print len(mag)
print str(mag)
del mag
運(yùn)行結(jié)果如下:
call me first
call me second
[1, 2, 3]
call __len__
3
call __str__
call __del__
- 比較函數(shù)
object.__lt__(self, obj) # 小于比較 <
object.__le__(self, obj) # 小于或等于 <=
object.__gt__(self, obj) # 大于 >
object.__ge__(self, obj) # 大于多等于 >=
object.__eq__(self, obj) # 等于 ==
object.__ne__(self, obj) # 不等于 !=
測(cè)試代碼如下:
# coding=utf-8
class MagicDemo(object):
def __init__(self, value):
self.value = value
def __lt__(self, obj):
print "call the __lt__"
return self.value < obj.value
def __le__(self, obj):
print "call the __le__"
return self.value <= obj.value
def __gt__(self, obj):
print "call the __gt__"
return self.value > obj.value
def __ge__(self, obj):
print "call the __ge__"
return self.value >= obj.value
def __eq__(self, obj):
print "call the __eq__"
return self.value == obj.value
def __ne__(self, obj):
print "call the __ne__"
return self.value != obj.value
if __name__ == '__main__':
mag1 = MagicDemo(5)
mag2 = MagicDemo(6)
print mag1 < mag2
print mag1 <= mag2
print mag1 > mag2
print mag1 >= mag2
print mag1 == mag2
print mag1 != mag2
運(yùn)行結(jié)果如下:
call the __lt__
True
call the __le__
True
call the __gt__
False
call the __ge__
False
call the __eq__
False
call the __ne__
True
- 屬性操作
object.__getattr__(self, attr) # 獲取屬性填大,僅當(dāng)屬性找不到時(shí)被調(diào)用
object.__setattr__(self, attr, val) # 設(shè)置屬性戒洼,當(dāng)設(shè)置屬性的值時(shí)被調(diào)用
object.__delattr__(self, attr) # 刪除屬性時(shí)被調(diào)用
object.__getattribute__(self, attr) # 獲取屬性,總是被調(diào)用允华,發(fā)生異常時(shí)調(diào)用__getattr__
object.__get__(self, attr) #(描述符)獲取屬性
object.__set__(self, attr, val) #(描述符)設(shè)置屬性
object.__delete__(self, attr) #(描述符)刪除屬性
測(cè)試代碼(描述符的三個(gè)屬性暫不說(shuō)明)
# coding=utf-8
class MagicDemo(object):
def __init__(self, value):
self.value = value
def __getattr__(self, attr):
"""找不到屬性時(shí)被調(diào)用"""
print "call __getattr__"
return "%s no found" % attr
def __setattr__(self, attr, value):
print "call __setattr__"
self.__dict__[attr] = value
def __delattr__(self, attr):
print "call __delattr__"
del self.__dict__[attr]
def __getattribute__(self, attr):
"""此方法只適用于新式類"""
print "call __getattribute__"
# return self.__dict__[name]
# 為了避免陷入死循環(huán)
return object.__getattribute__(self, attr)
if __name__ == '__main__':
mag = MagicDemo(5)
print "_______________"
mag.value = 6
print "_______________"
print mag.value
print "_______________"
print mag.xxx
測(cè)試結(jié)果如下:
call __setattr__
call __getattribute__
_______________
call __setattr__
call __getattribute__
_______________
call __getattribute__
6
_______________
call __getattribute__
call __getattr__
xxx no found
可以看出施逾,當(dāng)訪問(wèn)對(duì)象的屬性時(shí)敷矫,__getattribute__
總是被調(diào)用(新式類中有效),當(dāng)找不到屬性時(shí)汉额,將調(diào)用__getattr__
曹仗。其中__getattribute__
調(diào)用基類的方法是為了陷入死循環(huán),因?yàn)?code>__getattribute__總是無(wú)條件的被調(diào)用蠕搜。
- 自定義序列
object.__getitem__(self, key) # 得到單個(gè)序列元素
object.__setitem__(self, key, val) # 設(shè)置單個(gè)序列元素
object.__delitem__(self, key) # 刪除單個(gè)序列元素
object.__contains__(self, key) # 測(cè)試序列元素怎茫,使用in時(shí)調(diào)用
object.__iter__(self) # 返回一個(gè)迭代器
測(cè)試代碼:
# coding=utf-8
class MagicDemo(object):
def __init__(self):
self.value = dict()
def __getitem__(self, key):
print "call the __getitem__"
return self.value[key]
def __setitem__(self, key, val):
print "call the __setitem__"
self.value[key] = val
def __delitem__(self, key):
print "call the __delitem__"
del self.value[key]
def __contains__(self, key):
print "call the __contains__"
return key in self.value
if __name__ == '__main__':
mag = MagicDemo()
mag["name"] = "hello"
print "_______________"
print mag["name"]
print "_______________"
print "xxx" in mag
測(cè)試結(jié)果如下:
call the __setitem__
_______________
call the __getitem__
hello
_______________
call the __contains__
False
需要注意的是當(dāng)屬性為dict
時(shí)通過(guò)鍵值對(duì)進(jìn)行賦值,當(dāng)為list
時(shí)妓灌,通過(guò)下標(biāo)進(jìn)行賦值轨蛤。