16.python全栈之路:装饰器详解

装饰器

一.装饰器的意义

  比如:以下函数是供我们调用的,但是我们需要在每个函数中都添加同一个功能,该如何做到呢?

方法一:在每个函数中都加上新加的功能代码块

def f1():
	print("新功能")
	print("F1")

def f2():
	print("新功能")
	print("F2")

def f3():
	print("新功能")
	print("F3")

def f4():
	print("新功能")
	print("F4")

方法二:使用函数式编程,将需要添加的部分写成一个函数

def XX():
	print("新功能")   #在里面可以修改,新增的功能

def f1():
	XX()
	print("F1")

def f2():
	XX()
	print("F2")

def f3():
	XX()
	print("F3")

def f4():
	XX()
	print("F4")

  

方法三:前两种方法都没有遵守我们的开放封闭原则,对于函数内部,我们一般不允许修改。所以我们引入了装饰器  

def outer(func):
  def inner():
    print("添加在原函数之前")
    r = func()    #保留原函数的返回值
    print(‘添加在原函数之后‘)
    return r       #将保留的返回值返回回去
  return inner

@outer	           #等价于f1 = outer(f1)
def f1():
	print("F1")

def f2():
	print("F2")

def f3():
	print("F3")

def f4():
	print("F4")	

f1()                #执行函数,f1()已经等价于inner()了

二.简单装饰器的流程剖析

三.带参数的装饰器

3.1

#一般装饰器,不能装饰有参数的函数
def outer(func):  #func为待装饰的函数
	def inner():  #从上往下执行,遇到def inner,就将函数扔进内存空间,但不执行
		print("执行原函数前添加的部分")
		r = func() #接收原函数的返回值
		print("执行原函数后添加的部分")
		return r   #返回原函数的返回值
	return inner  #返回inner给index

@outer	           #index = outer(index)
def index():
	print("非常复杂的功能")
	return True

index()

3.2:修改方案:根据参数的个数,我们主要得修改装饰器的内层函数

#如果待包装函数有参数
#需要如何修改装饰器呢
def outer(func):
	def inner(a1, a2):
		print("执行原函数前添加的部分")
		r = func(a1, a2)
		print("执行原函数后添加的部分")
		return r
	return inner  

@outer
def index(a1, a2):
	print("非常复杂的功能")
	return a1 + a2

@outer
def home(s1, s2):
	print("非常复杂的功能")
	return "HOME"

ret1 = index(1, 2)  #应用了装饰器之后index变成装饰器的内层函数了

ret2 = home(1, 2)

3.3:但是,如果不同的待装饰函数的参数个数不一致该怎么办呢?

修改方案:使用动态参数,*arg**kwargs扩大接收参数的形式。

def outer(func):
	def inner(*arg ,**kwargs):
		print("执行原函数前添加的部分")
		r = func(*arg ,**kwargs)  #内部让*argj元组或**kwargs字典吐出参数,传入原函数
		print("执行原函数后添加的部分")
		return r
	return inner  

@outer
def home(s1):       #一个参数
	print("非常复杂的功能")
	return "HOME"

@outer
def index(a1, a2):  #两个个参数
	print("非常复杂的功能")
	return "INDEX"

@outer
def show(x1, x2, x3):#三个参数
	print("非常复杂的功能")
	return "SHOW"

ret1 = home(1)

ret2 = index(1, 2) 			 

ret3 = show(1, 2, 3)

  

四.使用多装饰器装饰一个函数

应用场景:例如有100个函数,其中10个函数需要加上一部分功能,

而另外90个函数还需要加上额外得一部分功能,怎么做?

方法一

def outer0(func):
	def inner(*arg ,**kwargs):
		print("执行原函数前添加的部分")
		r = func(*arg ,**kwargs)
		print("执行原函数后添加的部分")
		return r
	return inner  

def outer1(func):
	def inner(*arg ,**kwargs):
		print("执行原函数前添加的部分(额外)")
		print("执行原函数前添加的部分")
		r = func(*arg ,**kwargs)
		print("执行原函数后添加的部分")
		return r
	return inner  

@outer0   #功能1
def home(s1):
	print("非常复杂的功能")
	return "HOME"

@outer0	 #功能1
def index(a1, a2):
	print("非常复杂的功能")
	return "INDEX"

@outer1  #功能2
def show(x1, x2, x3):
	print("非常复杂的功能")
	return "SHOW"

ret1 = home(1)

ret2 = index(1, 2) 			 

ret3 = show(1, 2, 3)

缺点:装饰器outer2的代码与outer的代码有重复的部分,我们应该

尽量避免重复代码

方法二:改进版

def outer1(func):
	def inner(*arg ,**kwargs):
		print("执行原函数前添加的部分(1)")
		r = func(*arg ,**kwargs)
		print("执行原函数前添加的部分(4)")
		return r
	return inner  

def outer0(func):
	def inner(*arg ,**kwargs):
		print("执行原函数前添加的部分(2)")
		r = func(*arg ,**kwargs)
		print("执行原函数后添加的部分(3)")
		return r
	return inner

@outer0
def home(s1):
	print("非常复杂的功能")
	return "HOME"

@outer1   #先执行这个函数的装饰功能
@outer0	  #再执行这个函数的装饰功能
def index(a1, a2):
	print("非常复杂的功能")
	return "INDEX"

ret1 = home(1)
ret2 = index(1, 2)

多重装饰器流程分析:(原函数的两次变化)

  没应用装饰器之前,原函数就是原函数

  应用第一个装饰器(outer0))之后,原函数变成了outer0函数的内层函数了,由func保留了原函数

  应用第二个装饰器(outer1)之后,outer0的内层函数也就是此时的原函数传入了第二个装饰器里面

去了,替换成第二个装饰器的内存函数,并有第二个装饰器的参数func保存了原函数。

装饰过程

执行过程

装饰次序

五.装饰器的应用

  单层装饰器:比如京东的网页,在进入我的购物车之前需要登录,这个登录就是一个装饰器

  多层装饰器:对于京东的用户来说,有大家公共的页面,也有对于钻石vip和白金vip不同的

        页面,所以在使用第一层登录装饰器之后,还需要加上额外的用户权限的装饰器

时间: 2024-10-28 16:02:52

16.python全栈之路:装饰器详解的相关文章

Python全栈之路--Django ORM详解

ORM:(在django中,根据代码中的类自动生成数据库的表也叫--code first) ORM:Object Relational Mapping(关系对象映射) 我们写的类表示数据库中的表 我们根据这个类创建的对象是数据库表里的一行数据 obj.id  obj.name.....就是数据库一行数据中的一部分数据 ORM--First: 我们在学习django中的orm的时候,我们可以把一对多,多对多,分为正向和反向查找两种方式. class UserType(models.Model):

Python全栈day20(装饰器基本理论)

一,什么是装饰器 装饰器:本质就是函数,功能是为其他函数添加附加功能 原则 1,不修改被修饰函数的源代码 2,不修改被修饰函数的调用方式 举例说明:有一个求和函数要求就算出函数的运行时间 正常代码应该这样day20-1.py import time def cal(l): start_time=time.time() res=0 for i in l: res+=i stop_time=time.time() print('函数的运行时间是%s'%(stop_time-start_time))

Python全栈之路_01

Python全栈之路 前言:因为Python主要是在Linux和widows操作系统上使用所以,首先就介绍Pyhton在这两个平台上的安装和一些基础知识 Linux系统下安装Pyhton 1.工具 虚拟机:VMware workstation 12 Pro Linux系统:CentOS 64 位 VMware虚拟机安装很简单就不说明了. 在虚拟机安装CentOS 需要注意的是: 运行内存分配1G左右即可 可以开机按F2进入bios界面boot目录下选择启动设备选择Hard Drive为优先启动位

Python全栈之路系列之赋值与运算符

Python全栈之路系列之赋值与运算符 在继续下面的文章之前我们先来浏览一下Python为我们提供的几种运算符,定义两个变量,分别是a和b,a的值是10,b的值是20. 算术运算符 运算符 描述 实例 + 加,两个对象相加 a+b=30 - 减,两个对象相减,可能会得到负数 a-b=-10 * 乘,两数相称或是返回一个被重复若干次的字符串 a*b=200 / 除,两个对象相除 b/a=2 % 取膜,返回除法的余数 b%a=0 ** 幂,返回x的y次幂 a**b=10000000000000000

python 全栈之路

python 全栈之路 一. python 1. Python基础知识部分 Python Python那点事 Python windows和linux下 安装 Python2,Python3 Python 开启入坑之路 Python 基本数据类型 Python 那些零碎的知识点 Python -函数 Python - 面对对象 Python - 模块 Python - 文件操作 Python - python中经常踩得的坑 2. Python - 网络编程 3. Python - 并发编程 二.

Python全栈之路----常用模块----hashlib加密模块

加密算法介绍 HASH       Python全栈之路----hash函数 Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值. 简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数. HASH主要用于信息安全领域中加密算法,他把一

Python全栈之路Day22

初次编辑2017年10月28日,星期六 摘要一. 上节课复习二. 协程函数初始化装饰器三. send实现爬网页四. 面向过程的程序设计五. 列表生成式六. 三元表达式七.生成器表达式八. 声明式编程作业今日总结 摘要 引用:百度 列表生成式 生成器表达式 面向过程编程 递归 一. 上节课复习 可迭代的:对象有__iter__方法的都是可迭代的对象 迭代器:对象 .iter()得到的结果就是迭代器 迭代器的特征: 迭代器.next()取下一个值 优点: 提供了一种统一的迭代对象的方式,不依赖于索引

Python装饰器详解,详细介绍它的应用场景

装饰器的应用场景 附加功能 数据的清理或添加: 函数参数类型验证 @require_ints 类似请求前拦截 数据格式转换 将函数返回字典改为 JSON/YAML 类似响应后篡改 为函数提供额外的数据 mock.patch 函数注册 在任务中心注册一个任务 注册一个带信号处理器的函数 不同应用场景下装饰器实现 函数注册表 简单注册表 funcs = [] def register(func): funcs.append(func) return func @register def a(): r

Python全栈开发之8、装饰器详解

一文让你彻底明白Python装饰器原理,从此面试工作再也不怕了. 一.装饰器 装饰器可以使函数执行前和执行后分别执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator),装饰器的功能非常强大,但是理解起来有些困难,因此我尽量用最简单的例子一步步的说明这个原理. 1.不带参数的装饰器 假设我定义了一个函数f,想要在不改变原来函数定义的情况下,在函数运行前打印出start,函数运行后打印出end,要实现这样一个功能该怎么实现?看下面如何用一个简单的装饰器来实现