由Python通過__new__實現單例模式,所想到的__new__和__init__方法的區別


        之前通過讀書,了解到在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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM