python装饰器详解,多层装饰器,及带参数的装饰器。

pyhon学习有一段时间了,今天又碰到了Django的中间件,其实Django里面的中间件,就是用了多层的装饰器,然后去了解了一下多层装饰器,感觉有写东西差不多快忘了,也可能前面没学好。

现在重新记录,学习下。

普通装饰器:

def warp(func):
    print(‘我是装饰器,碰到需要装饰的函数,一开始执行这里‘)
    def inner(*args, **kwargs):
        print(‘这里才是真正的装饰开始!‘)
        res = func(*args, **kwargs)
        print(‘装饰结束‘)
        return res
    print(‘我这里是外围,先出去了,里面的等需要的时候执行‘)
    return inner

@warp   # 装饰器符号

def demo(x, y):
    return x + y

if __name__ == ‘__main__‘:
    demo(1, 2)
运行结果:

我是装饰器,碰到需要装饰的函数,一开始执行这里
我这里是外围,先出去了,里面的等需要的时候执行
这里才是真正的装饰开始!
装饰结束

其实我前面多层装饰卡住就是这里。

装饰器的本质就是一个函数,当你写好装饰器的函数从上而下运行时,一旦遇到@的提醒,python应该就开始禁图准备状态寻找需要装饰的函数,当遇到下面一个需要被装饰的函数demo时,

整个过程我在debug过程中发现,其实python马上跳转到开始去执行了warp函数,这就是刚开始我们输出前面两句的原因,其实这个时候,程序根本没有执行到demo(1,2)的地方。

在这个warp 程序的运行过程中,还发生一个命名转换的过程,就是demo=warp(),其实就是demo等于warp执行返回的函数inner,所以最后面执行demo(1,2)的时候,装饰器开始工作。

理解了这个,后面多层的装饰器更加好理解了。

下面上一个最简单的两层装饰器。

def deco1(func):
    print(‘func 1 in‘)
    def wrapper1():
        print(‘wrap1 in‘)
        func()
        print(‘wrap1 out‘)
    print(‘func 1 out‘)
    return wrapper1

def deco2(func):
    print(‘func 2 in‘)
    def wrapper2():
        print(‘wrap2 in‘)
        func()
        print(‘wrap2 out‘)
    print(‘func 2 out‘)
    return wrapper2

@deco1
@deco2
def foo():
    print(‘foo‘)

if __name__ == ‘__main__‘:
    foo()

执行结果为:

func 2 in
func 2 out
func 1 in
func 1 out
wrap1 in
wrap2 in
foo
wrap2 out
wrap1 out

其实一开我因为没能理解装饰器的原理在两个地方卡住了,第一个就是为什么先出的是

func 2 in
func 2 out
func 1 in
func 1 out

第二个问题就是为什么foo函数执行了一次,第二问题,网上查到了资料,第一个问题,通过对装饰的理解和debug的过程,也理解了。

通过介绍,整个程序是至上而下运行的,在运行过程到

@deco1
@deco2
def foo():一遇到需要装饰的函数def的时候,用要开始重新走装饰器,在走的过程中,先走跟函数近的装饰器deco2,所以输出了func 2 infunc 2 out再走deco1,所以输出了func 1 infunc 1 out。两个装饰器函数执行后,其实也运行了变量名替换。foo=deco1()即deco1程序执行的返回值wapper1,重点是来了wappper1里面的func其实已经成为deco2()即deco2执行程序的返回值wapper2,wapper2里面的func才是真正需要被装饰的函数foo。所以在warp1 in后面执行func的时候,直接跳到warp2了。所有在整个多层装饰的执行中,装饰器的执行是至上而下的,但在装饰器的(可以说内部调试中)是从哪个靠近需要被装饰的函数,哪个先执行,简单来说就是至下而上的。通过这样的理解,其实无论多少层装饰器,真正被装饰的原始函数将在最下面的那个装饰器执行,另外的只不过在一层接着一层的调用函数,其实也可以认为在一次次运行装饰过程。整个过程有点像压栈跟弹栈

最后一个带参数的装饰器。这个更加像一个内部返回来两次函数的定义函数,一共需要三个def来写这个函数。由于日常使用不过,我的理解可能也不是很充分。
def deco(params):     # params 为需要传入的参数
    print(‘floor1‘)
    def inner(func):
        print(‘floor2‘)
        def warp(*args, **kwargs):
            print(‘floor3‘)
            print(‘装饰开始‘)
            for i in range(params):
                func(*args, **kwargs)
            print(‘装饰结束‘)
            print(‘out3‘)
        print(‘out2‘)
        return warp
    print(‘out1‘)
    return inner

@deco(5)        #这个就是生成一个函数warp指向demo

def demo():
    print(‘ok‘)

if __name__ == ‘__main__‘:
    demo()

执行结果:

/Users/shijianzhong/Desktop/swiper/.venv/bin/python /Users/shijianzhong/Desktop/swiper/paramsfunc.py
floor1
out1
floor2
out2
floor3
装饰开始
ok
ok
ok
ok
ok
装饰结束
out3

Process finished with exit code 0

根据前面分析的,我废话少了点,其实在调试阶段,由于是带参数的装饰器,所以在这个三层def的情况,装饰器前期调试就已经运行了两层,且命名demo指向warp函数。

正常情况下,前面的两种情况理解,这个带参数的应该理解不难。

安装我的理解,可以先认为,在调试的过程中,装饰器自己先运行了一遍把函数返回了回来,然后用重命名了一下,这个带参数的,可以认为是装饰器自己运行了两遍,其中一遍是把参数写入内存中,待最里面的也就是真正需要装饰的函数使用。

今天就写这些。装饰器这下应该问题不大了,有空把闭包函数也写一下。

原文地址:https://www.cnblogs.com/sidianok/p/11564311.html

时间: 2024-08-06 23:23:57

python装饰器详解,多层装饰器,及带参数的装饰器。的相关文章

Python全栈__函数的有用信息、带参数的装饰器、多个装饰器装饰一个函数

1.函数的有用信息 代码1: 1 def login(username, password): 2 """ 3 此函数需要用户名,密码两个参数,完成的是登录的功能. 4 :return: True 登录成功. False登录失败. 5 """ 6 print(login.__name__) 7 print(login.__doc__) 8 print('登录成功...') 9 return True 10 11 print(login.__nam

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,要实现这样一个功能该怎么实现?看下面如何用一个简单的装饰器来实现

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

装饰器 一.装饰器的意义 比如:以下函数是供我们调用的,但是我们需要在每个函数中都添加同一个功能,该如何做到呢? 方法一:在每个函数中都加上新加的功能代码块 def f1(): print("新功能") print("F1") def f2(): print("新功能") print("F2") def f3(): print("新功能") print("F3") def f4(): p

装饰器详解

装饰器?What? 1:装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作. 2:至少两层函数 方式一: 理解方式 def auth(func): def inner(): print 'before' func() return inner def f1(): print 'f1' ret = auth(f1) f1 = ret f1() 执行结果: before f1 执行过程: # 1:执行def auth(func): #

Python带参数的装饰器

在装饰器函数里传入参数 # -*- coding: utf-8 -*- # 2017/12/2 21:38 # 这不是什么黑魔法,你只需要让包装器传递参数: def a_decorator_passing_arguments(function_to_decorate): def a_wrapper_accepting_arguments(arg1, arg2): print("I got args! Look:", arg1, arg2) function_to_decorate(ar

Python中带参数的装饰器

装饰器本身是用来是为一个函数是实现新的功能,并且不改变原函数的代码以及调用方式. 遇到这样一种问题: 众多函数调用了你写的装饰器,但客户有需求说,我想实现我可以随之控制装饰器是否生效. 那你就不可能在得到命令的时候去原函数头部去做删除和添加装饰器调用的命令.这是就可以用到带参数的装饰器,定义一个开关,调用装饰器的时候,把这个装饰器的开关参数给传递进去,这样当开关打开的时候装饰器生效,关闭的时候则只执行原函数的代码. 举例:开关参数为True的时候执行过程: 1 F = True #step 1

python 第十二天2018.04.01 带参数的装饰器,,函数的有用信息

一.带参数的装饰器,函数的有用信息 def func1(): '''此函数的功能是完成的登陆的功能 return: 返回值是登陆成功与否(true,false) ''' print(333) func1() print(func1.__name__)#func1 print(func1.__doc__)#此函数的功能是完成的登陆的功能,return: 返回值是登陆成功与否 打印函数名 from functools import wraps def wrapper(f): @wraps(f) de

python--装饰器详解

Python---装饰器详解 定义: 本质上是一个函数.作用是用来装饰另一个函数(即被装饰函数),给被装饰函数添加功能.前提是不能改变被装饰函数的源代码和调用方式.这样的一个函数称之为装饰器. 解析: 下面我们话不多说,直接用代码说明.下面是一个函数. 1 def add(): 2 b=1+2 3 print(b45 add() 程序输出: -------- 3 -------- 现在我要给这个函数增加一个解释性的句子,如下,我们可以编写一个装饰器: 1 #原函数 2 def add(): 3