Python單例的一種簡單寫法

weixin_33816946發表於2018-11-01

最原始的想法就是每個類都重寫new方法。

class Dog:
    dog = None

    def __new__(cls, *args, **kwargs):
        if cls.dog is None:
            cls.dog = object.__new__(cls)
            print('create singleton over')
        return cls.dog

    def __init__(self, name):
        print('init is called')
        self.name = name


# 下面這句話會報錯,因為Dog.dog目前為None
# print(Dog.dog.name)
x = Dog('x')
y = Dog('y')
print(x.name)  # y
print(y.name)  # y

最簡單的方法是把重寫new函式的工作放到一個父類裡面,這樣就能夠實現:只需要繼承父類就能夠讓自己變成單例。

"""
extend this class can make singleton class easily
"""


class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = object.__new__(cls)
        return cls._instance


class Dog(Singleton):
    def __init__(self, name):
        self.name = name


x = Dog('x')
y = Dog('y')
print(x.name, y.name)

Python的單例相對於Java的單例來說,簡明直接得多。我們依舊可以像建立物件一樣獲取單例的引用,而不必像Java那樣只能通過一個函式來獲取已經存在的物件。但是,Java單例的實現在語言層面上不做任何修改,Python的單例攔截了物件的建立(new)過程。因為Java的單例沒有對語言層面做修改,而Python的靈活性使得Java只是Python的一個子集,所以Java單例的那套建立方式在Python這裡同樣適用。

需要知道的一點是:Python的new函式才是真正的開闢空間的過程,init函式只是賦值、初始化的過程。

在Python中,我們建立的任何一個物件,無需重寫setattr方法即可隨便往物件上“懸掛”成員變數。

class Ha:
    pass


x = Ha()
x.dog = 3
print(x.dog)

相關文章