之前通過讀書,了解到在Python中可以通過__new__方法來實現單例模式,代碼一個示例如下,我就有了幾個疑問,什么是單例模式?__new__方法是用來做什么的?用__new__方法實現的單例模式,比如下面的MyClass類,會對類的初始化有影響嗎?會對類的實例方法、類方法、靜態方法有影響嗎?下面會說下我對這些概念的理解,如有錯誤,歡迎交流指出,在此表示感謝。
1 class SingleTon(object): 2 _instance = {} 3 4 def __new__(cls, *args, **kwargs): 5 if cls not in cls._instance: 6 cls._instance[cls] = super(SingleTon, cls).__new__(cls, *args, **kwargs) 7 print cls._instance 8 return cls._instance[cls] 9 10 11 class MyClass(SingleTon): 12 class_val = 22
首先說下單例模式,單例模式是確保一個類只有一個實例,並且這個實例是自己創造的,在系統中用到的都是這個實例。單例模式是設計模式的一種,關於設計模式和單例模式更具體的內容,可以查看相關的書本,在后面我也要好好學習一下這些東西。
下面主要說下__new__是用來干什么的,在Python中,__new__是用來創造一個類的實例的,而__init__是用來初始化這個實例的。既然__new__用來創造實例,也就需要最后返回相應類的實例,那么如果返回的是其他類的實例,結果如何呢?見下面的代碼。以下代碼運行后,首先打印出NoReturn __new__然后打印出other instance,最后通過type(t)可以看到t的類型是<class '__main__.Other'>,可以知道如果__new__中不返回本類的實例的話,是沒法調用__init__方法的。想要返回本類的實例,只需要把以下代碼中12行的Other()改成super(NoReturn, cls).__new__(cls, *args, **kwargs)即可。
1 class Other(object): 2 val = 123 3 4 def __init__(self): 5 print 'other instance' 6 7 8 class NoReturn(object): 9 10 def __new__(cls, *args, **kwargs): 11 print 'NoReturn __new__' 12 return Other() 13 14 def __init__(self, a): 15 print a 16 print 'NoReturn __init__' 17 18 t = NoReturn(12) 19 print type(t)
最后來說用__new__方法實現的單例模式,會對實例方法,類方法,靜態方法,實例變量和類變量有影響嗎?答案是對相應的方法是沒有影響的,但是如果用不同的變量都初始化了這個實例,在后面的變量中修改實例變量和類變量的話,前面的也會相應修改,而這也正好符合單例,無論多少個變量指向了這個實例,他們指向的是同一個。在__new__中產生完實例后,每次初始化實例對象,都是產生的同一個實例,而這個實例中相關的方法、變量還是和普通的實例一樣使用。測試代碼以及輸出如下:
1 class MyClass(SingleTon): 2 class_val = 22 3 4 def __init__(self, val): 5 self.val = val 6 7 def obj_fun(self): 8 print self.val, 'obj_fun' 9 10 @staticmethod 11 def static_fun(): 12 print 'staticmethod' 13 14 @classmethod 15 def class_fun(cls): 16 print cls.class_val, 'classmethod' 17 18 19 if __name__ == '__main__': 20 a = MyClass(1) 21 b = MyClass(2) 22 print a is b # True 23 print id(a), id(b) # 4367665424 4367665424 24 # 類型驗證 25 print type(a) # <class '__main__.MyClass'> 26 print type(b) # <class '__main__.MyClass'> 27 # 實例方法 28 a.obj_fun() # 2 obj_fun 29 b.obj_fun() # 2 obj_fun 30 # 類方法 31 MyClass.class_fun() # 22 classmethod 32 a.class_fun() # 22 classmethod 33 b.class_fun() # 22 classmethod 34 # 靜態方法 35 MyClass.static_fun() # staticmethod 36 a.static_fun() # staticmethod 37 b.static_fun() # staticmethod 38 # 類變量 39 a.class_val = 33 40 print MyClass.class_val # 22 41 print a.class_val # 33 42 print b.class_val # 33 43 # 實例變量 44 print b.val # 2 45 print a.val # 2