单例模式
一. 单例模式的概念及作用
1. 单例模式只创建一个对象,当多个对象被创建的时候,就会直接引用第一个对象的值
2. 创建对象时实参也会传递到 new 方法
但是一般 new 都不会使用参数,此时可以使用不定长参数来接收,
new 方法会在创建对象时,在初始化之前被调用,可以用 new 方法来判断是否已经创建了对象,来执行单例
二. _new_ 方法的使用及解读
(1)
class Person(object):
def __new__(cls):
"""
__new__ 当创建对象的时候会自动执行。
如果 __new__ 没有返回值,则这个类不能创建新对象。
如果 __new__ 想要创建新对象,则手动调用 object 来处理,并将生成的对象返回
"""
obj = object.__new__(cls) # 重写__new__方法之后,如果要创建新的实例对象,需要手动调用 object.__new__(cls)
print('new---obj=', obj)
return obj # 创建出来的实例对象,必须使用 return 返回
def __init__(self):
"""__init__ 在创建对象之后会自动执行"""
print('init---self=', self)
self.name = '张三'
print('----1----')
p = Person()
print('----2----')
print('p=', p)
(2)
class Person(object):
# 创建对象时实参也会传递到 __new__ 方法
# 但是一般 __new__ 都不会使用参数,此时可以使用不定长参数来接收
def __new__(cls, *args, **kwargs):
"""当创建对象的时候会自动执行"""
print('new---args=', args, 'kwargs=', kwargs)
obj = object.__new__(cls)
return obj
def __init__(self, name, age):
"""__init__ 在创建对象之后会自动执行"""
print('init---self=', self)
self.name = name
p = Person('李四', age=18)
print('p=', p
三. 单例模式 (在类中)
class Person(object):
instance = None # 定义类属性来记录创建好的对象
def __new__(cls, *args, **kwargs):
if cls.instance == None: # 只有当 instance 为 None 才创建新对象
cls.instance = object.__new__(cls)
return cls.instance
def __init__(self, name):
self.name = name
zs = Person('张三')
print(zs)
ls = Person('李四')
print(ls)
四. 单例模式(完善版)
class Person(object):
instance = None # 定义类属性来记录创建好的对象
is_first_run = True # 如果为 True 则说明是第一次创建对象
def __new__(cls, *args, **kwargs):
if cls.instance == None: # 只有当 instance 为 None 才创建新对象
cls.instance = object.__new__(cls)
return cls.instance
def __init__(self, name=''):
if Person.is_first_run:
self.name = name # 只有第一次创建对象才应该执行赋值
Person.is_first_run = False
def set_name(self, new_name): # 单例如果要修改属性,可以通过方法来处理
self.name = new_name
zs = Person('张三')
print(zs.name)
ls = Person() # 如果不想为初始化传递参数,可以使用缺省参数
print(ls.name)
ls.set_name('李四')
print(zs.name)
五. 单例模式 (在函数装饰器中)
– 单例模式
def sing_leton(cls):
# 定义一个类的字典
instances = {}
def get_instance(*args, **kwargs):
# 判断这个类的对象是不是在字典中
if cls not in instances:
# 说明不在字典中
instances[cls] = cls(*args, **kwargs)
# 如果不在字典中那么就是返回最早创建的对象
return instances[cls]
return get_instance
@sing_leton
class MyClass(object):
a = 1
c1 = MyClass()
c2 = MyClass()
print(c1 == c2)
print(id(c1))
print(id(c2))
"""
结果为:
True
140347536038880
140347536038880
"""
六. 静态方法与类方法
class Person(object):
__num = 0 # _Person__num
def __init__(self, name):
self.name = name
Person.__num += 1
def drink(self): # 方法第一个形参为实例对象的方法,是实例方法
print('喝东西')
@classmethod # 装饰器,语法糖
def get_num(cls): # 类方法,在方法上写一个 @classmethod,方法的第一个形参必定是类对象
# print(cls)
return Person.__num
@staticmethod
def add2num(a, b): # 静态方法。在方法上写一个 @staticmethod, 方法没有任何强制性的形参
print(a+b)
zs = Person('张三')
print('创建的对象个数为: %d' % Person.get_num()) # 类方法调用, 类名.方法名()
Person.add2num(11,22) # 静态方法调用,类名.方法名()
七. SUPER 与 _mro_ 的使用
1. super() 主要的作用是为了解决我们的父类被多次重复初始化的问题
2. super() 调用是 mro 顺序表中下一个类的对象