1. 程式人生 > >整理類的調用方式和構造方法

整理類的調用方式和構造方法

-c .com per reading 實現 super 變量 image next

前言:簡單版:類加括號執行__init__()對象加括號執行__call__(),

    全版:類是type創建的,創建類的時候type的__init__()方法自動執行,類加括號的時候執行type的__call__()方法

執行流程,

第零步 :編譯一下類,將類加載到內存

  執行type的__init__()方法,類是type的對象

第一步:執行type的__call__方法

    調用創建的類的__new__方法,用於創建對象。

    調用類的__init__方法,用於對對象初始化。

第二步:調用類的對象,即調用了類的call方法

執行流程

技術分享圖片

技術分享圖片
 1 class SingletonType(type):
2 def __init__(self, *args, **kwargs): 3 super(SingletonType, self).__init__(*args, **kwargs) 4 5 def __call__(cls, *args, **kwargs): 6 obj = cls.__new__(cls, *args, **kwargs) 7 cls.__init__(obj, *args, **kwargs) # Foo.__init__(obj) 8 return obj 9
10 11 class Foo(metaclass=SingletonType): 12 def __init__(self, name): 13 self.name = name 14 15 def __new__(cls, *args, **kwargs): 16 return object.__new__(cls) 17 18 19 obj = Foo(name) 20 print(obj)
Code

多線程

技術分享圖片
 1 import threading
 2 
 3 class SingletonType(type):
4 _instance_lock = threading.Lock() 5 def __call__(cls, *args, **kwargs): 6 if not hasattr(cls, "_instance"): 7 with SingletonType._instance_lock: 8 if not hasattr(cls, "_instance"): 9 cls._instance = super(SingletonType,cls).__call__(*args, **kwargs) 10 return cls._instance 11 12 class Foo(metaclass=SingletonType): 13 def __init__(self,name): 14 self.name = name 15 16 17 obj1 = Foo(name) 18 obj2 = Foo(name) 19 print(obj1,obj2)
Code

一. __init__()

  __init__()是對象的構造方法

 1 class Minal:
 2    pass
 3 
 4 print(type(Minal))
 5 print(Minal.__class__)
 6 print(Minal.__class__.__bases__)
 7 
 8 
 9 <class type>
10 <class type>
11 (<class object>,)

二.__new__()

  __new__(cls, *args, **kwargs)當創建對象時調用在init方法前調用,創建對象時調用,返回當前對象的一個實例;註意:這裏的第一個參數是cls即class本身

三.__call__()

  __call__(self, *args, **kwargs) 如果類實現了這個方法,相當於把這個類型的對象當作函數來使用,相當於 重載了括號運算符

技術分享圖片
 1 先來看看如下示例代碼:
 2 #call.py 一個class被載入的情況下。
 3 class Next:
 4   List = []
 5   
 6   def __init__(self,low,high) :
 7     for Num in range(low,high) :
 8       self.List.append(Num ** 2)
 9   
10   def __call__(self,Nu):
11     return self.List[Nu]
12 
13 如果 這樣使用:
14 b = Next(1,7)
15 print b.List
16 print b(2)
17 
18 那麽回饋很正常:
19 [1, 4, 9, 16, 25, 36]
20 9
21 
22 但如果這樣使用:
23 b = Next
24 b(1,7)
25 print b.List
26 print b(2)
27 $python ./call.py
28 [1, 4, 9, 16, 25, 36]
29 
30 Traceback (most recent call last):
31  File "cal.py", line 17, in <module>
32   print b(2) 
33 TypeError: __init__() takes exactly 3 arguments (2 given)
34 
35 __init__是初始化函數,在生成類的實例時執行。
36 而__call__是模擬()的調用,需要在實例上應用,因此這個實例自然是已經執行過__init__了。
37 你所舉的後面那個例子:
38 b = Next
39 這並不是創建實例,而是將class賦給一個變量。因此後面使用b進行的操作都是對Next類的操作,那麽其實就是:
40 Next(1,7)
41 print Next.List
42 print Next(2)
43 希望本文所述對大家的Python程序設計有所幫助。
View Code

來自於腳本之家,詳細請看腳本之家

整理類的調用方式和構造方法