python基础之装饰器详述

一、装饰器定义

在不改变被装饰对象内部代码和原有调用方式的基础上添加额外的功能。

二、简易版装饰器

import time
def index():
	time.sleep(3)
	print('亚洲最大的线上赌场开业了 双眼发红光的在线发牌!!!')
def home():
	time.sleep(1)
	print('重金求子')
def outer(func):  # func指向的是函数名index
	# func = index
	def get_time():
		start_time = time.time()
		func()
		end_time = time.time()
		print('函数运行时间:%s' % (end_time - start_time))
	return get_time  # 将get_time函数名返回出去
index = outer(index)  # outer(index函数名)
# 左侧的变量名index指代是函数名get_time
index()

image

三、装饰器进阶(解决参数和返回值问题)

import time
def index():
	time.sleep(3)
	print('亚洲最大的线上赌场开业了 双眼发红光的在线发牌!!!')
	return 'from index'
def login(name):
	time.sleep(1)
	print('%s正在发牌'%name)
	return 'from login'
def outer(func):  # func指向的是函数名login
	# func = login
	def get_time(*args,**kwargs):
		start_time = time.time()
		res = func(*args,**kwargs)  # 接收被装饰函数的返回值
		end_time = time.time()
		print('函数运行时间:%s' % (end_time - start_time))
		return res  # 执行完get_time之后返回被装饰函数执行之后的返回值
	return get_time  # 将get_time函数名返回出去
login = outer(login)
res1 = login('jason')
print(res1)

image

四、装饰器练习(认证功能)

# 定义一个登录状态
is_login = {'is_login': False}
# 判断用户是否登录,如果已经登录就直接调用,如果没有登录就输入账号密码登录
def login_auth(func):
	def auth(*args, **kwargs):
		if is_login.get('is_login'):  # 第一次取值是False,则if的子代码块不执行,直接同级往下执行
			res = func(*args, **kwargs)
			return res
		name = input('请输入您的用户名:').strip()
		psd = input('请输入您的密码:').strip()
		# 校验输入的账号密码是否正确,如果正确就直接调用,然后修改登录状态
		if name == 'jason' and psd == '123':
			res = func(*args, **kwargs)
			is_login['is_login'] = True
			return res
		# 如果不正确就提示账号或密码错误
		else:
			print('账户名或密码错误')
	return auth
index = login_auth(index)
index()

image

五、有参装饰器

def outer(source_data):
	# source_data = 'file'
	def login_auth(func):
		def auth(*args, **kwargs):
			# 2.校验用户名和密码是否正确
			# 数据的校验方式可以切换多种
			if source_data == 'file':
				# 从文件中获取用户数据并比对
				print('file文件获取')
			elif source_data == 'MySQL':
				# 从MySQL数据库中获取数据比对
				print('MySQL数据库获取')
			elif source_data == 'postgreSQL':
				# 从postgreSQL数据库中获取数据对比
				print('postgreSQL数据库获取')
			else:
				print('用户名或密码错误 无法执行函数')
		return auth
	return login_auth

@outer('file') # 先执行outer(file),然后再执行糖:@login—_auth()
def index():
	print('from index')

六、装饰器模板

def outer(func):
	def inner(*args, **kwargs):
		# 执行函数之前可以添加的额外功能

		res = func(*args, **kwargs)  # 执行被装饰的函数
		# 执行函数之后可以添加的额外功能

		return res  # 将被装饰函数执行之后的返回值返回
	return inner

image

七、装饰器语法糖

装饰器语法糖是写规范:语法糖必须紧贴在被装饰对象的上方
装饰器语法糖内部原理:会自动将下面紧贴着的名字当做参数传给装饰器函数调用

def outer(func):
	def inner(*args, **kwargs):
		print('执行函数之前可以添加的额外功能')
		res = func(*args, **kwargs)  # 执行被装饰的函数
		print('执行函数之后可以添加的额外功能')
		return res  # 将被装饰函数执行之后的返回值返回
	return inner
@outer  # index = outer(index)
def index(*args, **kwargs):
	print('from index')
@outer  # home = outer(home)
def home():
	print('from home')
index()
home()

image

八、双重语法糖

# 统计函数运行时间
import time
def get_time(func):
	# func = index
	def inner(*args, **kwargs):
		start_time = time.time()
		res = func(*args, **kwargs)  # 执行被装饰的函数 即 调用最开始的index()并返回值赋值给res
		end_time = time.time()
		print('函数执行时间:%s' % (end_time-start_time))
		return res  # 将被装饰函数执行之后的返回值返回
	return inner
# 校验用户登录装饰
def login_auth(func):
	# func = inner
	def inner1(*args, **kwargs):
		# 1.先获取用户的用户名和密码
		username = input('username>>>:').strip()
		password = input('password>>>:').strip()
		# 2.校验用户名和密码是否正确
		if username == 'jason' and password == '123':
			res1 = func(*args, **kwargs)  # 执行被装饰的函数  即 调用 inner()并把inner的返回值res赋值给res1
			return res1  # 将被装饰函数执行之后的返回值返回
		print('用户名或密码错误 无权限执行')
	return inner1
@login_auth   # inner = login_auth(inner)   # inner1 赋值给真正的index
@get_time  # index = get_time(index)  # index = inner
def index():
	time.sleep(1)
	print('from index')
index()  # 即 inner1()

九、装饰器修复技术

装饰器修复就是为了让装饰对象难以被察觉被装饰了。只需要在装饰器通用模板上加两句固定句式。因为用help()就可以查看函数的类型,会容易被发现,用了装饰器修复技术就看不出来了。

from functools import wraps  # 固定句式
def outer(func):
	@wraps(func)  # 固定句式
	def inner(*args, **kwargs):
		print('执行函数之前可以添加的额外功能')
		res = func(*args, **kwargs)  # 执行被装饰的函数
		print('执行函数之后可以添加的额外功能')
		return res  # 将被装饰函数执行之后的返回值返回
	return inner

image

十、装饰器小练习(三层语法糖)

# 判断七句print执行顺序
def outter1(func1):
	print('加载了outter1')
	def wrapper1(*args, **kwargs):
		print('执行了wrapper1')
		res1 = func1(*args, **kwargs)
		return res1
	return wrapper1

def outter2(func2):
	print('加载了outter2')
	def wrapper2(*args, **kwargs):
		print('执行了wrapper2')
		res2 = func2(*args, **kwargs)
		return res2
	return wrapper2

def outter3(func3):
	print('加载了outter3')
	def wrapper3(*args, **kwargs):
		print('执行了wrapper3')
		res3 = func3(*args, **kwargs)
		return res3
	return wrapper3

@outter1
@outter2
@outter3
def index():
	print('from index')
	
index()

image

posted @ 2021-11-18 00:22  90啊  阅读(68)  评论(0编辑  收藏  举报