最原始的想法就是每個類都重寫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)