Luckylau's Blog

你懂python吗(9)

python的单例模式

1.使用__new__方法

​ 实现__new__方法 并在将一个类的实例绑定到类变量_instance上, 如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回;如果cls._instance不为None,直接返回cls._instance 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls.instance
class Person(Singleton):
def __init__(self, name, age):
self.name = name
self.age = age
if __name__ == '__main__':
person1=Person('lucky',24)
person2=Person('lau',26)
print id(person1)
print id(person2)
#output
140057479545680
140057479545680

2.使用修饰符方法

​ 使用装饰器(decorator), 这是一种更pythonic,更elegant的方法,单例类本身根本不知道自己是单例的,因为他本身(自己的代码)并不是单例的。

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
def singleton(cls):
instances = {}
def _singleton(*args, **kw):
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return _singleton
@singleton
class Person(object):
def __init__(self, name=None, age=None):
self.name = name
self.age = age
if __name__ == '__main__':
person1=Person('lucky',24)
person2=Person('lau',26)
person3=Person()
print id(person1)
print id(person2)
print id(person3)
#output
140059880903312
140059880903312
140059880903312

3.使用metaclass方法

​ Person=Singleton(),Person其实为元类Singleton创建的一个实例类。创建Person的实例person1时,Person(‘lucky’,23)=Singleton.__call__(cls,args, *kwargs),这样就将Person的所有实例都指向了Person的属性_instance上,这种方法与使用__new__方法其实是相同的。

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
class Singleton(type):
def __call__(cls,*args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instance
class Person(object):
__metaclass__ = Singleton
def __init__(self, name=None, age=None):
self.name = name
self.age = age
if __name__ == '__main__':
person1=Person('lucky',23)
print person1.name
print person1.age
person2=Person()
person3=Person()
print id(person1)
print id(person2)
print id(person3)
#output
lucky
23
139786319061776
139786319061776
139786319061776

4.共享属性

​ 所谓单例就是所有引用(实例、对象)拥有相同的状态(属性)和行为(方法) 同一个类的所有实例天然拥有相同的行为(方法),只需要保证同一个类的所有实例具有相同的状态(属性)即可。所有实例共享属性的最简单最直接的方法就是__dict__属性指向(引用)同一个字典(dict)。

创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法。

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
class Singleton(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Singleton, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob
class Person(Singleton):
def __init__(self, name=None, age=None):
self.name = name
self.age = age
if __name__ == '__main__':
person1=Person('lucky',23)
person2=Person('lau',24)
person3=Person()
print id(person1)
print id(person2)
print id(person3)
print id(person1.__dict__)
print id(person2.__dict__)
#output
139890509018064
139890509018128
139890509018192
139890509022944
139890509022944

5.import方法

作为python的模块是天然的单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton()
# to use
from mysingleton import my_singleton
if __name__ == '__main__':
print id(my_singleton)
print id(my_singleton)
#output
140353398006352
140353398006352
Luckylau wechat
如果对您有价值,看官可以打赏的!