1. 程式人生 > >Python 需要單例模式嗎

Python 需要單例模式嗎

Python真的需要去實現單例模式嗎?——不需要。

因為,python有模組(module),最pythonic的單例典範。模組在一個應用程式中只有一份,本身就是單例的,將你所需要的屬性和方法,直接暴露在模組中變成模組的全域性變數和方法即可!

按照其他語言寫單例的方法:
# -*-coding:utf8-*-
import threading


lock = threading.Lock()


class Singleton(object):
    __instance = None

    def __new__(cls, *args, **kwargs):
        if not Singleton.__instance:
            try:
                lock.acquire()
                if not Singleton.__instance:
                    Singleton.__instance = object.__new__(cls, *args, **kwargs)
                    # Singleton.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs) # Same as the previous row.
            except Exception, e:
                print 'Singleton: init error : %s' % e
            finally:
                lock.release()
        return Singleton.__instance

    def __init__(self):
        pass


def test_singleton_in_thread():
    print id(Singleton())

if __name__ == "__main__":
    idx = 0
    while 1:
        threading.Thread(target=test_singleton_in_thread).start()
        idx += 1
        if idx > 0X100:
            break


# 應用舉例:工程中不同模組之間的資料共享。
# 如,在Openbridge-DR(平臺災備)中,flavor恢復後,建立新老資源的 flavor_id 的對應關係資料儲存到 Cache物件,後面恢復雲主機時,通過 Cache物件取資料。

class Cache(object):
    __instance = None
    __data = {}

    def __new__(cls, *args, **kwargs):
        if not Cache.__instance:
            try:
                lock.acquire()
                if not Cache.__instance:
                    Cache.__instance = object.__new__(cls, *args, **kwargs)
            except Exception, e:
                print 'Singleton Cache: init error:{}'.format(e.message)
            finally:
                lock.release()
        return Cache.__instance

    def get_data(self, k):
        return self.__data.get(k)

    def set_data(self, k, v):
        assert k
        self.__data[k] = v


# save data in a module.
Cache().set_data('key1', 'value1')
# get data in other module.
print Cache().get_data('key1')
直接使用類屬性:
class C():
    __data = {}

    def get_data(self, k):
        return self.__data.get(k)

    def set_data(self, k, v):
        assert k
        self.__data[k] = v

C().set_data('key1', 'value1')
print C().get_data('key1')

優化:
class C():
    __data = {}

    @classmethod
    def get_data(cls, k):
        return cls.__data.get(k)

    @classmethod
    def set_data(cls, k, v):
        assert k
        cls.__data[k] = v

C.set_data('key1', 'value1')
print C.get_data('key1')