面试题:
列举面向对象中带双下划线的特殊方法,如:__new__、__init____new__:创建实例
__init__:初始化实例
__call__:实例对象加( )会执行def __call__:... 方法里边的内容。
__del__:析构方法,当对象在内存中被释放时,自动触发执行。如当 del obj 或者应用程序运行完毕时,执行该方法里边的内容。
__enter__和__exit__:出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量;with中代码块执行完毕时执行__exit__里边的内容。
__module__:表示当前操作的对象在那个模块 obj.__module__
__class__ :表示当前操作的对象的类是什么 obj.__class__
__doc__:类的描述信息,该描述信息无法被继承
__str__:改变对象的字符串显示 print函数 --->obj.__str__()
__repr__:改变对象的字符串显示 交互式解释器 --->obj.__repr__()
__format__:自定制格式化字符串
__slots__:一个类变量 用来限制实例可以添加的属性的数量和类型
__get__():调用一个属性时,触发
__set__():为一个属性赋值时,触发
__delete__():采用del删除属性时,触发
用尽量多的方法实现单例模式
1:使用模块
Python的模块就是天然的单例模式。
因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。
因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。
例如:
class Single(object):
def foo(self):
pass
single = Single() # 实例好一个对象
将上面代码保存在文件test.py,要使用时,直接在其他文件中导入此文件中的对象,这个对象就是单例模式的对象. 如:from test import single
2:使用装饰器
def single(cls):
_instance = {}
def _singlewrap(*args, **kwargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kwargs)
return _instance[cls]
return _singlewrap
@single
class A(object):
def __init__(self, x=0):
self.x = x
a1 = A(1)
a2 = A(2)
print(a1 == a2) # True
3:基于__new__方法(推荐)
当我们实例化一个对象时,是先执行了类的__new__方法,我们没写时,默认调用object.__new__,实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式。
例:
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __new__(cls, *args, **kwargs):
if not hasattr(cls,'instance'):
cls.instance = super().__new__(cls)
return cls.instance
a = Person('p1',21)
b = Person('p2',22)
print(a == b, a.name == b.name)
# 这里的打印结果都是True,可见 a 和 b 都是同一个实例(实例 b 覆盖了实例 a)。
# 单例作用:
#第一、控制资源的使用,通过线程同步来控制资源的并发访问;
#第二、控制实例产生的数量,达到节约资源的目的;
#第三、作为通信媒介使用,也就是数据共享。比如,数据库连接池的设计一般采用单例模式,数据库连接是一种数据库资源。
# 应用场景:
Python的logger就是一个单例模式,用以日志记录
线程池、数据库连接池等资源池一般也用单例模式
Windows的资源管理器是一个单例模式
网站计数器