標籤:返回 百度 通訊 sha add one fan 產生 參數
1、什麼是魔法方法?
魔法方法就是可以給你的類增加魔力的特殊方法,如果你的對象實現(重載)了這些方法中的某一個,那麼這個方法就會在特殊的情況下被 Python 所調用,你可以定義自己想要的行為,而這一切都是自動發生的。它們經常是兩個底線包圍來命名的(比如 __init__,__lt__),Python的魔法方法是非常強大的,所以瞭解其使用方法也變得尤為重要!
2、__init__(self[, ...]),__new__(cls[, ...]),__del__(self)
__init__ 構造器,當一個執行個體被建立的時候初始化的方法。但是它並不是執行個體化調用的第一個方法,__new__才是執行個體化對象調用的第一個方法,它只取下 cls參數,並把其他參數傳給 __init__。 __new__很少使用,但是也有它適合的情境,尤其是當類繼承自一個像元組或者字串這樣不經常改變的類型的時候。
__new__ 使用時注意以下四點:
1. __new__ 是在一個對象執行個體化的時候所調用的第一個方法2. 它的第一個參數是這個類,其他的參數是用來直接傳遞給 __init__ 方法3. __new__ 決定是否要使用該 __init__ 方法,因為 __new__ 可以調用其他類的構造方法或者直接返回別的執行個體對象來作為本類的執行個體,如果 __new__ 沒有返回執行個體對象,則 __init__ 不會被調用4. __new__ 主要是用於繼承一個不可變的類型比如一個 tuple 或者 string
5. __new__ return的是一個構建的執行個體
__new__實現單例模式:
class Person(object): def __init__(self, name, age): self.name = name self.age = age def __new__(cls, *args, **kwargs): if not hasattr(cls,‘instance‘): cls.instance = super(Person,cls).__new__(cls) return cls.instancea = Person(‘p1‘,20)b = Person(‘p2‘,21)print(a == b)#這裡的列印結果是True,可見a,和b都是同一個執行個體#單例作用:#第一、控制資源的使用,通過線程同步來控制資源的並發訪問;#第二、控制執行個體產生的數量,達到節約資源的目的。#第三、作為通訊媒介使用,也就是資料共用,它可以在不建立直接關聯的條件下,讓多個不##相關的兩個線程或者進程之間實現通訊。#比如,資料庫連接池的設計一般採用單例模式,資料庫連接是一種資料庫資源。
__del__ 析構器,當執行個體被銷毀時調用
3、__call__(self[,args ...]),__getitem__(self,key),__setitem__(self,key,value)
__call__ 允許一個類的執行個體像函數一樣被調用
class Person(object): def __init__(self, name, age): self.name = name self.age = age self.instance = add def __call__(self,*args): return self.instance(*args)def add(args): return args[0] + args[1]a = Person(‘p1‘, 20)print(a([1,2]))#這裡將列印 3 #可見當建立a這個對象之後,如果定義了__call__函數則對象是可以像函數一樣調用的
__getitem__ 定義擷取容器中指定元素的行為,相當於self[key]
class Person(object): def __init__(self, name, age): self.name = name self.age = age self._registry = { ‘name‘: name, ‘age‘: age } def __call__(self, *args): return self.instance(*args) def __getitem__(self, key): if key not in self._registry.keys(): raise Exception(‘Please registry the key:%s first !‘ % (key,)) return self._registry[key]a = Person(‘p1‘, 20)print(a[‘name‘],a[‘age‘])#這裡列印的是 ‘p1‘ 20 #可見__getitem__使執行個體可以像字典一樣訪問
__setitem__ 設定容器中指定元素的行為,相當於self[key] = value
4、__getattr__(self,name),__getattribute__(self,name),__setattr__(self,name,value),__delattr__(self,name),__get__(self,instance,owner),__set__(self,instance,value),__delete__(self,instance)
__getattr__ 定義當使用者試圖訪問一個不存在屬性的時候的行為
__setattr__ 定義當一個屬性被設定的時候的行為
__getattribute__ 定義當一個屬性被訪問的時候的行為
class Person(object): def __init__(self, name, age): self.name = name self.age = age self._registry = { ‘name‘: name, ‘age‘: age } def __getattr__(self, item): print("don‘t have the attribute ",item) return False def __setattr__(self, key, value): self.__dict__[key] = value def __getattribute__(self, item): #注意此處不要用 self.__dict__[item] #因為self.__dict__依然會被__getattribute__攔截 這樣就會陷入迴圈 return object.__getattribute__(self,item)a = Person(‘p1‘, 20)print(a.hh) #這裡會列印 don‘t have the attribute hh 以及 Falsea.hh = ‘fdf‘ #這裡設定該屬性值為‘fdf‘print(a.hh) #這裡將列印出 fdf
__delattr__ 定義當一個屬性被刪除的時候的行為
__get__ 定義當描述符的值被取得的時候的行為
__set__ 定義當描述符的值被設定的時候的行為
__delete__ 定義當描述符的值被刪除的時候的行為
class Descriptor(object): def __init__(self): self.des = None def __get__(self, instance, owner): return instance.__dict__.get(self.des,None) def __set__(self, instance, value): instance.__dict__[self.des] = valueclass Person(object): des = Descriptor() #這裡的Descriptor就是一個描述符類 def __init__(self, name, age): self.name = name self.age = age self._registry = { ‘name‘: name, ‘age‘: age }a = Person(‘p1‘, 20)a.des = 10 #這裡會調用Descriptor的__set__方法print(a.des) #這裡會調用Descriptor的__get__方法
關於描述符有疑惑的朋友可以自己百度也可參考這篇文章 http://www.geekfan.net/7862/ ,網上也有很多相關的文章,這裡的重點不是描述符所以這裡不會有關於描述符過多的解釋!
python中的魔法方法