python装饰器使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python装饰器使用相关的知识,希望对你有一定的参考价值。

参考技术A

装饰器是从英文decorator翻译过来的,从字面上来看就是对某个东西进行修饰,增强被修饰物的功能,下面我们对装饰器做下简单介绍。

一、怎么编写装饰器

装饰器的实现很简单,本质是一个可调用对象,可以是函数、方法、对象等,它既可以装饰函数也可以装饰类和方法,为了简单说明问题,我们实现一个函数装饰器,如下代码:

有了这个装饰器,我们就可以打印出什么时候开始和结束调用函数,对于排查函数的调用链非常方便。

二、带参数的装饰器

上面的例子无论什么时候调用sum都会输出信息,如果我们需要按需输出信息怎么实现呢,这时就要用到带参数的装饰器了,如下代码:

对sum使用装饰器时没有参数,这时debug为0,所以调用sum时不会输出函数调用相关信息。

对multi使用装饰器时有参数,这时debug为1,所以调用multi时会输出函数调用相关信息。

三、函数名字问题

当我们打印被装饰后的函数名字时,不知道大家有没发现输出的不是函数本身的名字,如下代码会输出‘wrap’而不是‘sum’:

有时这种表现并不是我们想要的,我们希望被装饰后的函数名字还是函数本身,那要怎么实现呢?很简单,只需要引入functools.wraps即可,如下代码就会输出‘sum’了:

看完后是不是觉得python装饰器很简单,只要了解它的本质,怎么写都行,有好多种玩法呢。

Python 装饰器(装饰器的简单使用)

简单介绍了装饰器的一些基本内容,包含定义、本质、原则、如何实现。

1、装饰器的定义

定义:一种增加函数功能的简单方法,可以快速地给不同的函数或类插入相同的功能。

简单点就是:高阶函数+嵌套函数 -》装饰器 

2、装饰器本质

本质:函数 ,为其他函数进行装饰。

举个例子,现在有小狗100只,都有吃喝拉撒的功能,此时我想给其中50只小狗戴上装饰帽的功能,这个装饰帽就是装饰器的功能。但是它并不会改变小狗本身原有的功能。

3、装饰器的原则

原则1:不能修改被装饰的函数的源代码

原则2: 不能修改被装饰的函数的调用方式

4、装饰器的实现

大致了解需要有3个步骤:

4.1 函数即变量

4.2 高阶函数

4.3 嵌套函数

举个例子,装饰器count_time()函数实现对one()函数添加统计函数运行时间的功能

import time
def count_time(func):
    def deco():
        start = time.time()
        func()
        end = time.time()
        print("the func run time  is %s" %(end-start))
    return deco
@count_time
//通过语法糖@count_time 直接对one()函数添加统计时间的功能
def one():
    time.sleep(0.5)
    print(\'in the one\')

详细步骤如下:

4.1函数即变量

举个例子,比如把1赋值给x,内存会为x分配地址,且指向1 ;

此时x赋值给y,y同时也指向1;

 

同理,定义一个test()函数后,调用这个函数test(),内存会为这个函数分配一个地址,并指向函数体 

4.2 高阶函数

高阶函数一句话理解:函数中的变量包含函数。

A:把一个函数名当做实参传给另外一个函数(在不修改被装饰函数的源代码情况下为其添加功能)

B:返回值中包含函数名(不修改函数的调用方式)

举个例子,高阶函数代码如下:

import time
def count_time(func):
    def deco():
        start = time.time()
        func()
        end = time.time()
        print("the func run time  is %s" %(end-start))//程序运行时间:结束时间减去开始时间
   return deco

4.3 嵌套函数

很简单的一句话:嵌套函数表示的是函数里面有函数。

举个例子,one()函数中嵌套two()函数,嵌套函数代码如下

def one():
     print(\'in the one\')
     def two():
        print(\'in the two\')
     two()
#调用函数
one()

5、装饰器高级实现

装饰器涉及到有参数的语法糖、无参数的语法糖,后续有时间可以再次进行详细的了解~

 

#无参数的语法糖
import time
def show_time(func):
    def inner():  #内部参数
        start_time =time.time()
        func() #调用函数
        end_time=time.time()
        print(\'服务器响应时间:\',end_time-start_time)
    return inner

@show_time #等价于func=show_time(func)
def func():
    print(\'执行用例\')
    time.sleep(1)
#调用函数
func() 

 

#有参数的语法糖
import time #时间模块
def have_para(name): #参数名,执行者变量
    def show_time(func): #函数名调用变量
        def inner():#内部函数,函数体
            start_time =time.time()
            func()  #调用func()函数
            end_time=time.time()
            print(\'服务器响应时间:\',end_time-start_time)
            print(\'执行者:\',name)
        return inner  #返回inner对象
    return show_time #返回show_time对象

@have_para(\'wendy\') #等价于func=have_para(\'wendy\')
def func():
    print(\'执行用例\')
    time.sleep(1)
func()

 

user = \'xxx\'
password = \'123456\'
def A(B):
    print("B:",B)
    def outer_wrapper(func):
        def wrapper(*args, **kwargs):
            print("wrapper func args:", *args, **kwargs)
            if B == "bb":
                user_name = input("Username:")
                pass_word = input("Password:")
                if user == user_name and password == pass_word:
                    print("User has passed authentication")
                    ret = func(*args, **kwargs) 
                    print("---after authenticaion ")
                    return ret
                else:
                    exit("Invalid username or password")
            elif B == "QWW":
                print("have question")
        return wrapper
    return outer_wrapper
def one():
    print("in the one")

@A(B="bb")
def two():
    print("in the two")
    return " I\'m two"

@A(B="QWW")
def three():
    print("in the three")

one()
print(two())
three()

 

 

 

 

 

以上是关于python装饰器使用的主要内容,如果未能解决你的问题,请参考以下文章

python 装饰器

Python进阶装饰器(Decorator)

python 装饰器:装饰器实例内置装饰器

python 装饰器:装饰器实例内置装饰器

Python 装饰器(装饰器的简单使用)

python--装饰器