python学习笔记:利用contextlib和@contextmanager实现with语句上下文实例

import hashlib
from contextlib import contextmanager
#contextlib
'''
任何对象,只要正确实现了上下文管理,就可以用于with语句。
实现上下文管理是通过__enter__和__exit__这两个方法实现的,
也可以通过@contextmanager和closing函数实现
'''
print('用contextlib实现在函数调用前后打印log的功能:')
print('(1)contextlib: with...as...语句')
class Call(object):
	def __init__(self, func):
		self.__func = func
	
	def __enter__(self):
		print('Call %s()' % self.__func.__name__)
		return self
	
	def __exit__(self, exc_type, exc_value, traceback):
		if exc_type:
			print('Error')
		else:
			print('%s() End' % self.__func.__name__)
	
	def doProcess(self):
		self.__func()

def testFunc():
	print('I am testFunc, I am doing something...')

'''
执行顺序:
1,执行Call里面的__enter__函数
2,然后执行with语句里面的c.doProcess()
3,再执行Call里面的__exit__函数
结果:
	Call testFunc()
	I am testFunc, I am doing something...
	testFunc() End
'''
with Call(testFunc) as c:
	c.doProcess()

#用@contextmanager实现和上面一样的功能,在函数调用前后打印log
print('(2)contextlib: with...as...语句,用@contextmanager实现')
from contextlib import contextmanager
class Call2(object): #不用实现__enter__和__exit__函数了
	def __init__(self, func):
		self.__func = func
	
	def doProcess(self):
		self.__func()

@contextmanager
def callWraper(func):
	print('Call %s()' % func.__name__)
	c = Call2(func)
	yield c
	print('%s() End' % func.__name__)

'''
执行流程:
1, with语句先执行callWraper函数里面yield之前的语句
2,yield调用会执行with语句内部的所有语句c.doProcess()
3,最后执行yield之后的语句
'''
with callWraper(testFunc) as c:
	c.doProcess()

#实现用with语句可以在用户执行操作前连接数据库,在执行完操作后关闭数据库的功能

#由字符串获取md5摘要信息串
def md5DigestGet(str):
	str += '!@#$%^'  #为了使简单的字符串不被黑客破解,将字符串添油加醋
	md5 = hashlib.md5()
	md5.update(str.encode('utf-8'))
	return md5.hexdigest()

class myDb(object):
	def __init__(self, users):
		self.__linkFlag = False #连接标志
		self.__usersLoginDigests = {} #保存用户名和密码的摘要信息
		for name, passward in users.items():
			md5Digest = md5DigestGet(name + passward)
			self.__usersLoginDigests[name] = md5Digest
	
	def getDbInfo(self):
		return self.__usersLoginDigests
	
	def loginCheck(self, name, passward):
		if md5DigestGet(name + passward) == self.getDbInfo()[name]:
			print('%s Login success' % name)
		else:
			print('%s Login fail' % name)

	def linkDb(self):
		self.__linkFlag = True
		return self.loginCheck
	
	def unlinkDb(self):
		self.__linkFlag = False

def linkDb(db): #连接到数据库
	print('Trying to link to db...')
	checkFunc = db.linkDb()
	print('Link db success..')
	return checkFunc

def unlinkDb(db):
	print('Trying to unlink db...')
	db.unlinkDb()
	print('unLink db success..')

@contextmanager
def userLoginCheck(db, name, passward):
	checkFunc = linkDb(db)
	yield checkFunc
	unlinkDb(db)
users = {'kite':'abc_12345', 'jim':'xyz@1345', 'tom':'hello_***'} #用户名和密码
db = myDb(users)

print('-----------------------------------------------------------')
userName = 'kite'
passWard = 'abc_12345'
with userLoginCheck(db, userName, passWard) as checkFunc:
	checkFunc(userName, passWard)
print('-----------------------------------------------------------')
userName = 'jim'
passWard = 'xyz@1346'
with userLoginCheck(db, userName, passWard) as checkFunc:
	checkFunc(userName, passWard)
'''
执行结果:
-----------------------------------------------------------
Trying to link to db...
Link db success..
kite Login success
Trying to unlink db...
unLink db success..
-----------------------------------------------------------
Trying to link to db...
Link db success..
jim Login fail
Trying to unlink db...
unLink db success..
'''



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值