在Python中建立單例 - Creating a singleton in Python

問題:

This question is not for the discussion of whether or not the singleton design pattern is desirable, is an anti-pattern, or for any religious wars, but to discuss how this pattern is best implemented in Python in such a way that is most pythonic. 這個問題不是爲了討論是否須要單例設計模式 ,是不是反模式,仍是針對任何宗教戰爭,而是要討論如何以最pythonic的方式在Python中最好地實現此模式。 In this instance I define 'most pythonic' to mean that it follows the 'principle of least astonishment' . 在這種狀況下,我定義「最pythonic」來表示它遵循「最少驚訝的原理」 python

I have multiple classes which would become singletons (my use-case is for a logger, but this is not important). 我有多個將成爲單例的類(個人用例用於記錄器,但這並不重要)。 I do not wish to clutter several classes with added gumph when I can simply inherit or decorate. 當我能夠簡單地繼承或修飾時,我不但願增長gumph來使幾個類雜亂無章。 設計模式

Best methods: 最佳方法: 函數


Method 1: A decorator 方法1:裝飾器

def singleton(class_):
    instances = {}
    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]
    return getinstance

@singleton
class MyClass(BaseClass):
    pass

Pros 優勢 ui

  • Decorators are additive in a way that is often more intuitive than multiple inheritance. 裝飾器的添加方式一般比多重繼承更直觀。

Cons 缺點 this

  • While objects created using MyClass() would be true singleton objects, MyClass itself is aa function, not a class, so you cannot call class methods from it. 使用MyClass()建立的對象將是真正的單例對象,而MyClass自己是一個函數,而不是類,所以您不能從中調用類方法。 Also for m = MyClass(); n = MyClass(); o = type(n)(); 一樣對於m = MyClass(); n = MyClass(); o = type(n)(); m = MyClass(); n = MyClass(); o = type(n)(); then m == n && m != o && n != o 而後m == n && m != o && n != o

Method 2: A base class 方法2:一個基類

class Singleton(object):
    _instance = None
    def __new__(class_, *args, **kwargs):
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

class MyClass(Singleton, BaseClass):
    pass

Pros 優勢 spa

  • It's a true class 這是一個真正的課堂

Cons 缺點 .net

  • Multiple inheritance - eugh! 多重繼承-好! __new__ could be overwritten during inheritance from a second base class? __new__是否能夠在從第二個基類繼承時被覆蓋? One has to think more than is necessary. 人們必須思考的超出了必要。

Method 3: A metaclass 方法3: 元類

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

#Python2
class MyClass(BaseClass):
    __metaclass__ = Singleton

#Python3
class MyClass(BaseClass, metaclass=Singleton):
    pass

Pros 優勢 設計

  • It's a true class 這是一個真正的課堂
  • Auto-magically covers inheritance 自動神奇地涵蓋繼承
  • Uses __metaclass__ for its proper purpose (and made me aware of it) __metaclass__用於其適當的目的(並使我意識到這一點)

Cons 缺點 code

  • Are there any? 有嗎

Method 4: decorator returning a class with the same name 方法4:裝飾器返回具備相同名稱的類

def singleton(class_):
    class class_w(class_):
        _instance = None
        def __new__(class_, *args, **kwargs):
            if class_w._instance is None:
                class_w._instance = super(class_w,
                                    class_).__new__(class_,
                                                    *args,
                                                    **kwargs)
                class_w._instance._sealed = False
            return class_w._instance
        def __init__(self, *args, **kwargs):
            if self._sealed:
                return
            super(class_w, self).__init__(*args, **kwargs)
            self._sealed = True
    class_w.__name__ = class_.__name__
    return class_w

@singleton
class MyClass(BaseClass):
    pass

Pros 優勢 對象

  • It's a true class 這是一個真正的課堂
  • Auto-magically covers inheritance 自動神奇地涵蓋繼承

Cons 缺點

  • Is there not an overhead for creating each new class? 建立每一個新類沒有開銷嗎? Here we are creating two classes for each class we wish to make a singleton. 在這裏,咱們爲但願建立單例的每一個類建立兩個類。 While this is fine in my case, I worry that this might not scale. 雖然這對我來講很好,但我擔憂這可能沒法擴展。 Of course there is a matter of debate as to whether it aught to be too easy to scale this pattern... 固然,要擴展這種模式是否太容易了還有爭議。
  • What is the point of the _sealed attribute _sealed屬性的意義是什麼
  • Can't call methods of the same name on base classes using super() because they will recurse. 沒法使用super()在基類上調用相同名稱的方法,由於它們會遞歸。 This means you can't customize __new__ and can't subclass a class that needs you to call up to __init__ . 這意味着您不能自定義__new__ ,也不能將須要調用__init__類做爲子類。

Method 5: a module 方法5:一個模塊

a module file singleton.py 一個模塊文件singleton.py

Pros 優勢

  • Simple is better than complex 簡單勝於複雜

Cons 缺點


解決方案:

參考一: https://stackoom.com/question/SMlJ/在Python中建立單例
參考二: https://oldbug.net/q/SMlJ/Creating-a-singleton-in-Python
相關文章
相關標籤/搜索