-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Singleton.py
103 lines (93 loc) · 3.12 KB
/
Singleton.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
'''
单例模式,核心结构中只包含一个被称为单例类的特殊类,类的对象只能存在一个
三个要点: 某个类只有一个实例; 必须自行创建这个实例; 必须自行向整个系统提供这个实例
'''
'''
方法1: 实现__new__方法,然后将类的一个实例绑定到类变量_instance上
如果cls._instance为None, 说明该类没有被实例化过, new一个该类的实例,并返回
如果cls._instance不是None, 直接返回_instance
'''
class Singleton1(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
orig = super(Singleton1, cls)
cls._instance = orig.__new__(cls, *args, **kwargs)
return cls._instance
class Myclass(Singleton1):
a = 1
one = Myclass()
two = Myclass()
# one和two完全相同, 可以用id(), ==, is检测
print(id(one))
print(id(two))
print(one == two) # True
print(one is two) # True
two.a = 3
print(one.a) # 3
'''
方法2:共享属性;所谓单例就是所有引用(实例、对象)拥有相同的的状态(属性)和行为(方法)
同一个类的所有实例天然拥有相同的行为(方法)
只需要保证一个类的所有实例具有相同的状态(属性)即可
所有实例共享属性的最简单方法就是__dict__属性指向(引用)同一个字典(dict)
'''
class Borg(object):
_state = {}
def __new__(cls, *args, **kwargs):
ob = super(Borg, cls).__new__(cls, *args, **kwargs)
ob.__dict__ = cls._state
return ob
class MyClass2(Borg):
a = 1
one = MyClass2()
two = MyClass2()
two.a = 3
print(one.a)
# one 和 two 是两个不同的对象,id,==,is对比结果可以看出
print(id(one)) # 18410480
print(id(two)) # 18410512
print(one == two) # False
print(one is two) # False
# 但是one和two具有相同的(同一个)__dict__属性
print(id(one.__dict__)) # 14194768
print(id(two.__dict__)) # 14194768
'''
方法3:装饰器版本decorator
这是一种更pythonic,更elegant的方法
单例类本身根本不知道自己是单例的,因为他自己的代码并不是单例的
'''
def singleton(cls, *args, **kwargs):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
class MyClass3(object):
a = 1
def __init__(self, x = 0):
self.x = x
one = MyClass3()
two = MyClass3()
two.a = 3
print(one.a) # 3
print(id(one)) # 8842576
print(id(two)) # 8842576
print(one == two) # True
print(one is two) # True
one.x = 1
print(one.x) # 1
print(two.x) # 1
'''
方法4:import方法
python中的模块module在程序中只被加载一次,本身就是单例的
可以直接写一个模块,将你需要的方法和属性,写在模块中当做函数和模块作用域的全局变量即可,根本不需要写类。
'''
# mysingleton.py
# class My_Singleton(object):
# def foo(self):
# pass
# my_singleton = My_Singleton()
# to use
from mysingleton import my_singleton
my_singleton.foo()