zoukankan      html  css  js  c++  java
  • Python之路【第四篇】:Python基础(19)——装饰器

    #普通装饰器
    # (@+函数名),需要记住关键两点:
    #功能:
    #1、自动执行outer函数,并且将其下面的函数名f1当作参数传递
    #2、将outer函数的返回值,重新赋值给f1

    # #装饰器必备
    # ####第一:函数名和执行函数####
    # def foo(): #创建函数
    # print('hello') #函数体
    # foo #表示是函数名,代指整个函数
    # foo() #表示执行f00函数
    # # 输出:hello

    # ####第二:函数被重新定义###
    # def foo():
    # print("foo1")
    #
    # foo = lambda : print("foo2") #lambda表达式,无参数
    #
    # foo() #执行下面的lambda表达式,而不是原来的foo函数,foo函数已经被重新定义





    # #同名函数被覆盖
    # def f1(): #1
    # print(123)
    #
    # def f1():#2 #4
    # print(456) #5
    # f1() #3
    # #输出: 456


    #f1函数作为参数进行传递
    # def f1(): #1 创建f1函数 #6执行f1()函数,结果是打印输出123
    # print("123") #7
    # #没有return,默认返回None
    # def f2(xxx): #2 创建f2函数 #4 接收到传递的f1以后,xxx也是代指f1函数的整体,f2(xxx)就相当于f2(f1)
    # ret = xxx() #5 xxx()就等于是f1(),f1()就代表去执行f1()这整个函数。
    #
    # f2(f1) #3 调用f2函数,f1作为参数(f1没有单引号和双引号是一个函数名; f1没有带括号(),代指的是f1函数的整体,f1作为参数传递给xxx


    # #装饰器 流程剖析 分解功能1:自动执行outer()函数,并将下面的函数名f1作为参数传递 ()
    # # def outer(): #TypeError: outer() takes 0 positional arguments but 1 was given 翻译:outer需要0个参数,但传递了1个参数
    # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。
    # print(123) #4 执行函数体:打印123
    # print(func) #5 执行函数体:打印func参数,输出:<function f1 at 0x0000000000B28620>
    # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递。即@outer等价于outer(f1)
    # def f1():
    # print("F1")


    # #装饰器 流程剖析 分解功能2:将outer函数的返回值111,重新赋值给f1
    # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。
    # return "111" #4 将outer函数的返回值111,重新赋值给f1。
    # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递
    # def f1():
    # print("F1")
    # print(f1) #5 原来的f1函数被覆盖,被重新赋值为111.


    #问题解析:
    #4 (为什么outer函数的返回值111,就重新赋值给了f1,f1并没有调用outer(f1)函数啊?)这个问题纠结了我至少4个小时。感谢绍宁指点。如下:
    # @outter 等价于 outter(f1)
    # 等价于f1=outter(f1)
    # outter函数的返回值是111
    # 所以f1就变成了111
    # 装饰器就是在把原来的函数包起来加工一下,但是加工后还是叫原来的函数名,用了装饰器后 原来的函数名 等于装饰器函数的返回值
    # 参考链接:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html
    # #函数是一个对象,可以赋值给其他对象变量,通过变量可以调用该函数。
    # def foo():
    # print("test")
    # f = foo #注意没有使用圆括号,因为不是在调用函数
    # f()
    # # # 输出:test
    # print(foo.__name__)#通过函数对象_name_属性,可以拿到函数的名字:
    # #输出:foo
    # print(f.__name__)
    # # 输出:foo



    #装饰器 流程剖析 将outer函数的返回值,换成其他函数。
    #注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111
    #我们能把f1换成111,同理,也能换成一个其他函数。
    # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。
    # # return "111" #4 将outer函数的返回值111,重新赋值给f1。
    # def inner(): #4 在内存中创建inner函数 #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。
    # print("在执行老的f1函数之前执行命令") #9 在执行老的f1函数之前执行
    # func() #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数
    # print("在执行老的f1函数之后执行命令") #11 在执行老的f1函数之后执行
    # return inner #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。
    # #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数
    # #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能
    #
    # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递
    # def f1():
    # print("F1")
    # # print(f1) #6 原来的f1函数被覆盖,被重新赋值为inner函数。# <function outer.<locals>.inner at 0x00000000030AF1E0>


    # #装饰器 流程剖析 返回值
    # #注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111
    # #我们能把f1换成111,同理,也能换成一个其他函数。
    # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。
    # # return "111" #4 将outer函数的返回值111,重新赋值给f1。
    # def inner(): #4 在内存中创建inner函数 #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。
    # print("在执行老的f1函数之前执行命令") #9 在执行老的f1函数之前执行
    # # ret = func() #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数
    # r = func() #10 执行func()函数,等于执行原f1()函数,原f1函数有返回值,定义变量r用于接收原f1函数的返回值
    # print("在执行老的f1函数之后执行命令") #11 在执行老的f1函数之后执行
    # return r #12 r代表原f1函数的返回值,新f1函数执行之后将原f1函数的返回值返回给函数调用者。(函数遇到return就不再向下执行,所以把return放在最下面)
    # return inner #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。
    # #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数
    # #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能
    #
    # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递
    # def f1():
    # print("F1")
    # return "原f1函数返回值FFFF" #原f1函数有返回值FFFF
    # # print(f1) #6 原来的f1函数被覆盖,被重新赋值为inner函数。# <function outer.<locals>.inner at 0x00000000030AF1E0>



    # #装饰器 流程剖析 1个参数
    # #注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111
    # #我们能把f1换成111,同理,也能换成一个其他函数。
    # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。
    # # return "111" #4 将outer函数的返回值111,重新赋值给f1。
    # def inner(a): #4 在内存中创建inner函数 #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。#8.1外部调用新f1函数的实参,首先传递给形参“a”
    # print("在执行老的f1函数之前执行命令") #9 在执行老的f1函数之前执行
    # # ret = func() #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数
    # r = func(a) #10 执行func()函数,等于执行原f1()函数,原f1函数有返回值,定义变量r用于接收原f1函数的返回值 #10.1将函数调用者传递的参数传递给原f1()函数。
    # print("在执行老的f1函数之后执行命令") #11 在执行老的f1函数之后执行
    # return r #12 r代表原f1函数的返回值,新f1函数执行之后将原f1函数的返回值返回给函数调用者。(函数遇到return就不再向下执行,所以把return放在最下面)
    # return inner #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。
    # #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数
    # #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能
    #
    # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递
    # def f1(arg): #10.2接收函数调用者传递的参数arf = a
    # # print("F1")
    # print(arg)
    # return "原f1函数返回值FFFF" #原f1函数有返回值FFFF
    # # print(f1) #6 原来的f1函数被覆盖,被重新赋值为inner函数。# <function outer.<locals>.inner at 0x00000000030AF1E0>



    #注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111
    #我们能把f1换成111,同理,也能换成一个其他函数。
    # def outer(func): #1在内存中创建outer函数 #3执行outer(f1)函数 #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。
    # # return "111" #4 将outer函数的返回值111,重新赋值给f1。
    # def inner(a): #4 在内存中创建inner函数 #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。#8.1外部调用新f1函数的实参,首先传递给形参“a”
    # print("在执行老的f1函数之前执行命令") #9 在执行老的f1函数之前执行
    # # ret = func() #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数
    # r = func(a) #10 执行func()函数,等于执行原f1()函数,原f1函数有返回值,定义变量r用于接收原f1函数的返回值 #10.1将函数调用者传递的参数传递给原f1()函数。
    # print("在执行老的f1函数之后执行命令") #11 在执行老的f1函数之后执行
    # return r #12 r代表原f1函数的返回值,新f1函数执行之后将原f1函数的返回值返回给函数调用者。(函数遇到return就不再向下执行,所以把return放在最下面)
    # return inner #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。
    # #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数
    # #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能
    #
    # @outer #2 自动执行outer()函数,并将下面的函数名f1作为参数传递
    # def f1(arg): #10.2接收函数调用者传递的参数arf = a
    # # print("F1")
    # print(arg)
    # return "原f1函数返回值FFFF" #原f1函数有返回值FFFF
    # # print(f1) #6 原来的f1函数被覆盖,被重新赋值为inner函数。# <function outer.<locals>.inner at 0x00000000030AF1E0>















    #装饰器 流程剖析 函数传递多个参数使用万能参数,*args,**kwargs

    def outer(func): #创建outer函数;f2函数作为参数传递给outer函数,func代指装饰的原函数,即原f2函数。
    def inner(*args,**kwargs): #创建嵌套的inner函数,a,b接收f2函数调用者传递的参数 #*args,**kwargs可以接收任意参数
    # pass
    print("before:执行原函数之前")
    r = func(*args,**kwargs) #执行原函数,接收原函数返回值;a,b将调用者传递的参数传递给原f2函数。#python自动把*args,**kwargs里面的参数传递给原函数 print("after:执行原函数之后") return r #返回原函数返回值 return inner #将inner函数的返回值重新赋值给f2函数,inner函数即为新f2函数。(inner后面无括号)@outerdef f1(): print("F1") return "f1"@outerdef f2(a1,a2): print(a1,a2) return "f2"
  • 相关阅读:
    BZOJ2301——莫比乌斯&&整除分块
    2019HDU多校第五场A fraction —— 辗转相除法|类欧几里得
    AKS素性检测
    2019牛客多校B generator 1——十进制快速幂
    BZOJ 3884——欧拉降幂和广义欧拉降幂
    libevent HTTP client 的实现
    google proto buffer安装和简单示例
    setenv LD_LIBRARY_PATH
    Centos6.4下安装protobuf及简单使用
    lrzsz
  • 原文地址:https://www.cnblogs.com/jiangnanmu/p/5558043.html
Copyright © 2011-2022 走看看