python單例模式,可以繼承,不會重復執行初始化函數的版本


網上最長見的版本:

1 class Singleton(object):
2     __instance=None
3     def__init__(self):
4         pass
5     def__new__(cls,*args,**kwd):
6         if Singleton.__instance is None:
7             Singleton.__instance=object.__new__(cls,*args,**kwd)
8         return Singleton.__instance

坑1:每次實例化時,__init__()都會執行一次

原因:python每次實力化一個類先調用__new__方法,再調用__init__方法。在__new__方法中,在不讓子類有感知的情況下,無法跳過該機制

坑2:該類無法繼承,如果有多個類繼承了該基類,那么每次實例化不同的類得到的結果都是第一次實例化時得到的類

原因:__instance作為Singleton這個類的類變量存在,當第一次實例化該類的子類時,__instance被設置為實例化的結果,之后實例化每個子類時,在__new__函數中檢測到該變量已設置就不會再去實例化,所以該值也就不會變化。

 

改進:

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '__instance'):
            print('in new')
            cls.__instance = object.__new__(cls, *args, **kwargs)
            cls.__instance.__Singleton_Init__(*args, **kwargs)
        return cls.__instance
        
    def __Singleton_Init__(self):
        print("__Singleton_Init__")

填坑1:該類規定子類的初始化函數是__Singleton_Init__,這樣就可以在__new__方法中控制初始化方法的調用

填坑2:__new__方法的cls參數是最上的層子類,判斷cls.__instance是否被設置就是在判斷各個子類是否有__instance成員變量,這樣就可以愉快的繼承了

 

再挖個坑:if not hasattr(cls, '__instance'),為什么這里可以檢查cls的“私有成員”

 

一個例子:

# -*- coding: utf-8 -*-
class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '__instance'):
            print('before new')
            print(cls)
            cls.__instance = object.__new__(cls, *args, **kwargs)
            print('after new')
            cls.__instance.__Singleton_Init__(*args, **kwargs)
        return cls.__instance
    def __init__(self):
        print("__init__")
        
    def __Singleton_Init__(self):
        print("__Singleton_Init__")
        
class BB(Singleton):
    pass
        
class CC(Singleton):
    pass
        
c = CC()
c1 = CC()
b=BB()
b.a=2
c.a=3
print(id(c), id(c1))
print(b.a, c.a)

 


免責聲明!

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



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