练习题
“”"
1、通过装饰器实现单例模式,只要任意一个类使用该装饰器装饰,
那么就会变成一个单例模式的类。(面试真题)
2、为第一次课创建的DB类,实现上下文管理器协议,实现退出上下文时,自动关闭游标,断开连接
“”"
第一道题
解题思路:先定义一个类作为装饰器,并且 定义 构造方法 init(),以及 call() 方法,以便于 被装饰的类函数可正常实例化。并且在__call__()中进行单例判断,若未实例化则进行实例化,已实例化的则直接返回实例化后对象
class Decorator:
__instance = None
def __init__(self, func):
print('===初始化===')
self.func = func
def __call__(self, *args, **kwargs):
print('--------调用方法-------')
if not self.__instance:
self.__instance = self.func()
return self.__instance
@Decorator
class demo:
def __init__(self):
print('初始化构建demo')
print('demo')
@Decorator
class demo1:
def __init__(self):
print('初始化构建demo1')
print('demo1')
使用闭包函数作为装饰器的方式
思路是给传入的类对象中进行定义一个类属性,判断该类属性是否为空
def single(cls):
cls.instance = None
def wrapper(*args, ** kwargs):
if not cls.instance:
cls.instance = cls(*args, **kwargs)
return cls.instance
return wrapper
同样思路下 使用类来作为装饰器
class single:
def __init__(self, cls):
self.cls = cls
cls.instance = None
def __call__(self, *args, **kwargs):
if not self.cls.instance:
self.cls.instance = self.cls(*args, **kwargs)
return self.cls.instance
第二道题
原先的DB类如下:
class DB:
def __init__(self):
self.con = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123456',
database='demo',
charset='utf8',
cursorclass=pymysql.cursors.DictCursor,
)
self.cur = self.con.cursor()
def query_sql(self, sql):
self.cur.execute(sql)
return self.cur.fetchall()
def execute_sql(self, sql):
self.cur.execute(sql)
return self.con.commit()
def close(self):
self.cur.close()
self.con.close()
解题思路:实现上下文管理协议,重点在于 增加 enter() 以及 exit() 两个函数,以及配合with 故代码如下
@Decorator
class DB:
def __init__(self):
self.con = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123456',
database='demo',
charset='utf8',
cursorclass=pymysql.cursors.DictCursor,
)
self.cur = self.con.cursor()
def __enter__(self):
print('-----enter----')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('------退出前关闭连接和游标--------')
self.cur.close()
self.con.close()
print('---------关闭成功------')
def query_sql(self, sql):
self.cur.execute(sql)
return self.cur.fetchall()
def execute_sql(self, sql):
self.cur.execute(sql)
return self.con.commit()
with DB() as f:
sql = "select * from student"
res = f.query_sql(sql)
print(res)