一、__new__方法是在 類 建立實例 的時候 自動調用的。python
二、實例是經過類裏面的__new__方法是在 類 建立出來的閉包
三、先調用__new__方法建立實例,再調用 __init__方法初始化實例。函數
四、__new__方法,,後面括號裏的cls表明 的是類自己spa
#通常不會重寫__new__方法,經常使用在單例模式 class Hero(object): def __init__(self,name): self.name = name print('%s調用了我進行初始化'%self.name) def __new__(cls, *args, **kwargs): print(args) #*args 傳入位置參數 #**kwargs 傳入關鍵字參數 #用於間接傳參 print('new方法被調用了,要建立一個對象') return object.__new__(cls) #重寫__new__方法不要忘記 #cls 表明類自己 moran = Hero('墨染') print(id(moran) ) ni = Hero('AA') print(id(ni)) # print(moran.name) ('墨染',) new方法被調用了,要建立一個對象 墨染調用了我進行初始化 3072197388 ('AA',) new方法被調用了,要建立一個對象 AA調用了我進行初始化 3072197420
咱們能夠看到建立實例的時候,自動調用了__new__,方法和__init__方法,而且 是先調用的__new__再調用的__init__方法,打印 cls 的時候顯示的這個Hero類3d
單例模式實現的原理:經過重寫__new__方法,讓__new__只能進行一次實例建立。code
class Hero: __instance = None #定義一個私有 類屬性 並賦值爲None def __new__(cls, *args, **kwargs): #建立對象 if cls.__instance == None: #而後咱們判斷它是否是等於None,若是等於None,咱們調用父類的方法建立一個實例對象,並把返回的對象賦值給 __instance,而且返回__instance cls.__instance = object.__new__(cls) return cls.__instance else: #若是__instance不等於None,那就說明已經建立了對象 咱們直接把__instance返回出去。 return cls.__instance moran = Hero() print(id(moran)) yanzhi = Hero() print(id(yanzhi)) 3072236972 3072236972
兩個實例的ID是相同的,意味着第二 次建立的時候,並無真正的去建立,而是引用的第一次創的實例, 同一個實例的不一樣名字對象
class Hero: attr1 = 1001 attr2 = 1002 def __getattribute__(self, item):
print('------bute------') def __getattr__(self, item): print('get調用的時候觸發了我') def __setattr__(self, key, value): print('set調用的時候觸發了我') yanzhi = Hero()
yanzhi.attr1
# 屬性查找 print(hasattr(yanzhi,'attr2')) #屬性存在返回Ture 不存在返回False 判斷是否存在屬性,果屬性存在則進行下一步操做 print(getattr(yanzhi,'attr1')) #屬性存在返回屬性值 不存在報錯 獲得屬性值 # 增長屬性 yanzhi.name = '炎志' setattr(yanzhi,'age',18) print(yanzhi.name) print(yanzhi.age) # 修改屬性 setattr(yanzhi,'age',28) #設置屬性值 print(yanzhi.age) # 刪除屬性 # delattr(yanzhi,'attr1') # print(yanzhi.attr1) ------bute------ ------bute------ True ------bute------ None set調用的時候觸發了我 set調用的時候觸發了我 ------bute------ None ------bute------ None set調用的時候觸發了我 ------bute------ None
描述符協議:python描述符是一個「綁定行 爲」的對象屬性,在描述符協議中,它能夠 經過方法重寫屬性的訪問。這些方法有 __get__(), __set__(), 和__delete__()。 blog
若是這些方法中的任何一個被定義在一個對 象中,這個對象就是一個描述符開發
魔術方法的做用實際上是讓開發人員可以更加靈活的控制類的表現形式get
class Hero: def __get__(self, instance, owner): print("--------get----------") def __set__(self, instance, value): print("---------set---------") def __delete__(self, instance): print("-------delete--------") class MyClass: m = Hero() attr = 111 c = MyClass() c.m c.m = 1111 del c.m --------get---------- ---------set--------- -------delete--------
可以實如今不修改原來的函數的基礎上添加功能,修飾函數。
#閉包複習,裝飾器引入 def func(a): def fun1(): print("---------func------------") print(a) a() return fun1 @func def fun(): print("我是-----fun------") # # func(fun)() # result = func(fun) # result() fun() ---------func------------ <function fun at 0xb7249a4c> 我是-----fun------
#簡單裝飾器 def f1(func): def f2(): print("裝飾的功能") func() return f2 @f1 def func(): print("基礎功能代碼") func() 裝飾的功能 基礎功能代碼
#經過裝飾器實現功能 def f1(func): def f2(a,b): print("a加b的結果是:%s" % (a + b)) print("a減b的結果是:%s" % (a - b)) print("a除b的結果是:%s" % (a / b)) func(a,b) return f2 @f1 def func(a,b): print("a乘b的結果是:%s"%(a*b)) func(11,2) a加b的結果是:13 a減b的結果是:9 a除b的結果是:5.5 a乘b的結果是:22
python的類裏面中還有三個內置的裝飾器:
class MyClass(object): attr = '人' @property #讓方法像屬性同樣被訪問 將類裏面的一個方法變成屬性 def func1(self): print('--------這是func1---------') @classmethod # def func2(cls): #cls 標識類方法 self訪問不到 print('--------這是func2---------') @staticmethod def func3(): #類的靜態方法 print('---------這是fun3---------') def func4(self): print('----------這是fun4---------') #類方法能夠經過實例和類去訪問yan.func2 實例方法只能經過實例去訪問 yan = MyClass() print(yan.attr) yan.func1 yan.func2() MyClass.func2() yan.func3() MyClass.func3() yan.func4() 人 --------這是func1--------- --------這是func2--------- --------這是func2--------- ---------這是fun3--------- ---------這是fun3--------- ----------這是fun4---------
類也能夠作裝飾器,可是須要定義 __call__ 方法
# #類裝飾器 class Text(object): def __init__(self,fun): self.fun = fun def __call__(self, *args, **kwargs): print('裝飾器的功能代碼') self.fun() @Text def func(): print('原來的功能代碼') # func = Text(func) func() 裝飾器的功能代碼 原來的功能代碼
#查看函數運行時間: >>> import time >>> def run_time(func): ... def new_fun(*args,**kwargs): ... t0 = time.time() ... print('star time: %s'%(time.strftime('%x',time.localtime())) ) ... back = func(*args,**kwargs) ... print('end time: %s'%(time.strftime('%x',time.localtime())) ) ... print('run time: %s'%(time.time() - t0)) ... return back ... return back