Skip to main content

装饰器

1. 装饰器的一步步实现

## 装饰器:装饰器定义一个函数,该函数是用来为其他函数添加额外的工能
## 装饰器就是不修改源代码以及调用方式的基础上增加新功能

## 开放封闭原则
	# 开放:指的是对拓展工能是开放的
	# 封闭: 指的是对修改源代码是封闭的
    
## 添加一个计算代码运行时间的工能(修改了源代码)    
import time
def index(name,age):
	start = time.time()
	time.sleep(3)
	print('我叫%s,今年%s岁'%(name,age))
	end = time.time()
	print(end - start)
index(age = 18,name = 'yanchen')

# --------------------------------------------------------------------------

def index1(name,age):
	print('我叫%s,今年%s岁' % (name, age))

def wrapper():
	start = time.time()
	index1(name="yanchen", age=18)
	time.sleep(3)
	end = time.time()
	print(end - start)
    
wrapper()
# 解决了修改原函数,但是也改变了函数调用方式

# --------------------------------------------------------------------------------------
def index1(name,age):
	print('我叫%s,今年%s岁' % (name, age))

def wrapper(name,age):
	start = time.time()
	index1(name, age)
	time.sleep(3)
	end = time.time()
	print(end - start)
    
wrapper('yanchen',18)

# -----------------------------------------------------------------------------------
def index1(name,age):
	print('我叫%s,今年%s岁' % (name, age))

def wrapper(*args,**kwargs):
	start = time.time()
	index1(*args,**kwargs)
	time.sleep(3)
	end = time.time()
	print(end - start)
    
wrapper('yanchen',age = 18)

# ------------------------------------------------------------------------------------
def index1(name,age):
	print('我叫%s,今年%s岁' % (name, age))
    
def outer():
    func = index
    def wrapper(*args,**kwargs):
        start = time.time()
        fun(*args,**kwargs)
        time.sleep(3)
        end = time.time()
        print(end - start)
    return wrapper
    
f = outer()  # f本质就是wrapper函数

### 继续改进
def index1(name,age):
	print('我叫%s,今年%s岁' % (name, age))
    
def outer(fun):
    def wrapper(*args,**kwargs):
        start = time.time()
        fun(*args,**kwargs)
        time.sleep(3)
        end = time.time()
        print(end - start)
    return wrapper
    
f = outer(index1)  # f本质就是wrapper函数
f(name='yanchen',age=18)


# 继续改进,偷梁换柱
def index1(name,age):
	print('我叫%s,今年%s岁' % (name, age))
    
def outer(fun):
    def wrapper(*args,**kwargs):
        start = time.time()
        fun(*args,**kwargs)
        time.sleep(3)
        end = time.time()
        print(end - start)
    return wrapper
    
index1 = outer(index1)  # f本质就是wrapper函数
index1(name='yanchen',age=18)  # 新功能加上了,也没有修改函数的调用方式

# ---------------------------------------------------------

2. 装饰器最终版本

# 被装饰函数有返回值
########### 装饰器最终版本

def index1(name,age):
	print('我叫%s,今年%s岁' % (name, age))
    return [name,age]  # 有返回值
    
def outer(fun):
    def wrapper(*args,**kwargs):
        start = time.time()
        arg = fun(*args,**kwargs)
        time.sleep(3)
        end = time.time()
        print(end - start)
        return arg # 返回index1 的返回值
    return wrapper
    
index1 = outer(index1)  # f本质就是wrapper函数
res = index1(name='yanchen',age=18)  # 新功能加上了,也没有修改函数的调用方式,把原函数的返回值也拿到了
# --------------------------------------------------------------------------------------------------

3. 装饰器语法糖

def outer(fun):
    def wrapper(*args,**kwargs):
        start = time.time()
        arg = fun(*args,**kwargs)
        time.sleep(3)
        end = time.time()
        print(end - start)
        return arg # 返回index1 的返回值
    return wrapper   
@outer
def index1(name,age):
	print('我叫%s,今年%s岁' % (name, age))
    return [name,age]  # 有返回值


# -----------------------------------------------
# 与原函数伪装的更像一点

from functools import wraps  # 用于把原函数的属性特征赋值给另一个函数
def outer(fun):
    @wraps(fun) # 可以把fun函数的所有属性特征加到wrapper函数身上
    def wrapper(*args,**kwargs):
    
        # wrapper.__name__ = fun.__name__
        # wrapper.__doc__ = fun.__doc__
        # 手动赋值麻烦
        
        start = time.time()
        arg = fun(*args,**kwargs)
        time.sleep(3)
        end = time.time()
        print(end - start)
        return arg # 返回index1 的返回值
    return wrapper

@outer
def index1(name,age):
    '''我是index1'''   # 通过help(index)函数来查看 文档信息,可以通过index.__doc__ = 'xxxxx' 来给某个函数赋值文档信息
    # 通过 index__name__ 可以获得函数的名字,也可以对其进行赋值
	print('我叫%s,今年%s岁' % (name, age))
    return [name,age]  # 有返回值

4. 有参装饰器

4.1 不用语法糖

### 不用语法糖
def auth(func,db_type):
	def wrapper(*args,**kwargs):
		name = input('your name:').strip()
		pwd = input('your password:').strip()

		if db_type == 'file':
			print('基于文件验证')
			if name == 'yanchen' and pwd == 'yc123':
				print('login success')
				res = func(*args,**kwargs)
				return res
			else:
				print('用户名或者密码错误!!')

		elif db_type == 'mysql':
			print('基于mysql验证')
		elif db_type == 'ldap':
			print('基于ldap验证')
		else:
			print('基于其他途径验证')
	return wrapper


def index(x,y):
	print('index->>%s:%s'%(x,y))

index = auth(index,'file')
index('yanchen',18)

4.4.2 语法糖01

#---------------------------------------------------------------------
# 语法糖01
def auth(db_type = "file"):
	def deco(func):
		def wrapper(*args,**kwargs):
			name = input('your name:').strip()
			pwd = input('your password:').strip()

			if db_type == 'file':
				print('基于文件验证')
				if name == 'yanchen' and pwd == 'yc123':
					print('login success')
					res = func(*args,**kwargs)
					return res
				else:
					print('用户名或者密码错误!!')

			elif db_type == 'mysql':
				print('基于mysql验证')
			elif db_type == 'ldap':
				print('基于ldap验证')
			else:
				print('基于其他途径验证')
		return wrapper
	return deco

deco = auth(db_type = 'file')
@deco
def index(x,y):
	print('index->>%s:%s'%(x,y))
index('yanchen',18)

deco = auth(db_type = 'mysql')
@deco
def index(x,y):
	print('index->>%s:%s'%(x,y))
index('yanchen',18)

4.3 标准语法糖

# ---------------------------------------------------------------------------------
# 标准语法糖模板
def auth(外界传递的参数):
	def deco(func):
		def wrapper(*args,**kwargs):
              '''自己扩展的功能'''  
             res = func(*args,**kwargs)
             return res
         return wrapper
	return deco
@auth(外界传递的参数)
def index(x,y):
    print(x,y)
    return(x,y)


# 标准语法糖02(例子)
def auth(db_type = "file"):
	def deco(func):
		def wrapper(*args,**kwargs):
			name = input('your name:').strip()
			pwd = input('your password:').strip()

			if db_type == 'file':
				print('基于文件验证')
				if name == 'yanchen' and pwd == 'yc123':
					print('login success')
					res = func(*args,**kwargs)
					return res
				else:
					print('用户名或者密码错误!!')

			elif db_type == 'mysql':
				print('基于mysql验证')
			elif db_type == 'ldap':
				print('基于ldap验证')
			else:
				print('基于其他途径验证')
		return wrapper
	return deco


@auth(db_type = 'file')
def index(x,y):
	print('index->>%s:%s'%(x,y))
index('yanchen',18)

@auth(db_type = 'file')
def index(x,y):
	print('index->>%s:%s'%(x,y))
index('yanchen',18)