资讯专栏INFORMATION COLUMN

Python - 装饰器decorator

HackerShell / 1188人阅读

摘要:在这种代码运行期间动态增加功能的方式,称之为装饰器。四接收特定类型参数的装饰器装饰器可以接收参数,当调用装饰器返回的函数时,也就调用了包裹函数,把参数传入包裹函数,它将参数传递给被装饰的函数。执行结果执行结果


【题外话】心塞塞 心情down down down 有段时间没用装饰器了,然后然后问着就跪了~~~
回来翻了翻资料和代码......


一、什么是装饰器
装饰器,decorator,本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。

装饰器通过不修改核心代码而增强核心代码部分的功能。例如在函数前插入日志、权限校验、事务处理等场景。
而且可以抽离出大量与函数功能无关的雷同代码并重用。

二、早期实现:不是装饰器的装饰器

Python中函数也可以看做是一个对象,可以赋值给变量,并通过变量调用该函数。

例如:

def foo():
   print("2017-06-08")
f = foo    # 将函数赋值给变量,f为函数对象
f()
# 返回结果:
2017-06-08
三、语法糖@ 实现简单装饰器

假设现在要增强foo()的功能,例如,在函数调用前打印日志。但是又不希望修改foo()函数的定义。在这种代码运行期间动态增加功能的方式,称之为“装饰器”。
如下:

def testfunc(func):
    print("testfunc")
    def wrapper():
        print("%s %s() called" %(time.ctime(),func.__name__))
        return func()
    return wrapper
@testfunc 
def foo():
    print("foo1()")

foo()  # 相当于执行testfunc(foo) ->wrapper(foo) -> foo()

执行结果:

testfunc
Wed Sep 12 15:01:13 2018 foo() called
foo1()

说明:执行foo()前,先执行testfunc(foo),再执行wrapper(),返回时调用foo()本身。

四、接收特定类型参数的装饰器

装饰器可以接收参数,当调用装饰器返回的函数时,也就调用了包裹函数,把参数传入包裹函数,它将参数传递给被装饰的函数。

如下:

def testfunc_with_args(func):
    def wrapper_argus(arg1, arg2):
        print("I got args! Look:", arg1, arg2)
        func(arg1, arg2)
    return wrapper_argus
@testfunc_with_args
def full_name(first_name, last_name):  # 带参数,将参数传给被装饰的函数
    print("My name is", first_name, last_name)

full_name("Peter", "Venkman")  # 调用

执行结果:

I got args! Look: Peter Venkman
My name is Peter Venkman
五、带不定参数的装饰器

当有多个函数需要调用装饰器,但是函数的参数各不同时,该如何实现呢?总不能一个函数对应一个装饰器吧。这时候就可以用带不定参数的装饰器进行实现。
如下:

def log(func):
    def wrapper(*args,**kwargs):        # 可接受各种参数
        print("call %s():"% func.__name__)
        return func(*args,**kwargs)     # 返回一个函数
    return wrapper                      # 装饰器返回一个函数,进入到wrapper()

@log      # @log放到now()的定义处,相当于执行语句:now = log(now)
def now_1(a,b):
    print("now()1:a+b = ",a+b)
@log
def now_2(a,b,c):
    print("now_2():a+b+c = ",a+b+c)

now_1(1,2)
now_2(1,2,3)

运行一下哦~

六、多个装饰器

当一个函数想要加入多项功能时,可以考虑使用多层装饰器,就是要注意一下装饰器的执行顺序。
举个栗子:

# 注意代码的执行顺序
def deco_1(func):
    print("------111111------")
    def wrapper(*args,**kwargs):    # 包裹函数,参数与原函数的参数一致
        print("start: this is deco_1.")
        func(*args,**kwargs)
        print("end: deco_1.")
    return wrapper  # 返回值是一个包裹函数
def deco_2(func):
    print("------222222------")
    def wrapper(*args,**kwargs):
        print("start: this is deco_2.")
        func(*args,**kwargs)
        print("end: deco_2.")
    return wrapper

@deco_1
@deco_2
def now_1(a,b):
    print("now()1:a+b = ",a+b)

now_1(1,2)

运行结果:

# 结果,注意执行顺序:
------222222------
------111111------
start: this is deco_1.
start: this is deco_2.
now()1:a+b =  3
end: deco_2.
end: deco_1.
七、装饰器本身带参数

除了给被装饰的函数带参数,装饰器本身也可以带参数。

def logging(level):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            print("[{level}]: enter function {func}()".format(level=level, func=func.__name__))
            return func(*args, **kwargs)
        return inner_wrapper
    return wrapper
    
@logging(level="INFO")
def say(something):
    print("say {}!".format(something))

@logging(level="DEBUG")
def do(something):
    print("do {}...".format(something))

say("hello")
do("my work")

执行结果:

# 执行结果:
[INFO]: enter function say()
say hello!
[DEBUG]: enter function do()
do my work...

❤ thanks for watching, keep on updating...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/42421.html

相关文章

  • python 装饰 part2

    摘要:装饰器传参被装饰的函数带有参数的情况接上一篇,直接上代码函数也就是被装饰的函数的运行时间是装饰器的正确使用,不需要传参装饰器的正确使用,需要传参此时不用再像上面一样赋值,可以直接调用返回值被装饰的函数有返回值在装饰器内部需被装饰函数的调用 python 装饰器 传参 被装饰的函数带有参数的情况 接上一篇,直接上代码 import time def decorator(func): ...

    sanyang 评论0 收藏0
  • Python装饰

    摘要:一引用书流畅的书二基本概念问题装饰器是什么解答严格来说,装饰器只是语法糖,装饰器是可调用的对象,可以像常规的可调用对象那样调用,特殊的地方是装饰器的参数是一个函数问题装饰器有什么特性解答装饰器有个特性,一是可以把被装饰的函数替换成其他函数, 一, 引用 [书] 流畅的Python [书] Effective Python 二, 基本概念 showImg(https://segme...

    aisuhua 评论0 收藏0
  • Python 装饰使用指南

    摘要:装饰器是可调用的对象,其参数是另一个函数被装饰的函数。第二大特性是,装饰器在加载模块时立即执行。另一个常见的装饰器是,它的作用是协助构建行为良好的装饰器。 装饰器是可调用的对象,其参数是另一个函数(被装饰的函数)。 装饰器基础知识 首先看一下这段代码 def deco(fn): print I am %s! % fn.__name__ @deco def func(): ...

    NeverSayNever 评论0 收藏0
  • Python知识点:理解和使用装饰 @decorator

    摘要:使用类装饰器,优点是灵活性大,高内聚,封装性。不过不用担心,有,本身也是一个装饰器,它的作用就是把原函数的元信息拷贝到装饰器函数中,使得装饰器函数也有和原函数一样的元信息。 showImg(https://segmentfault.com/img/bVbrFWb?w=742&h=484);Python的装饰器(decorator)是一个很棒的机制,也是熟练运用Python的必杀技之一。...

    cyqian 评论0 收藏0
  • Python装饰vs装饰模式

    摘要:希望引以为戒郑传装饰模式如果你了解,你肯定听过装饰器模式。在面向对象中,装饰模式指动态地给一个对象添加一些额外的职责。就增加一些功能来说,装饰模式比生成子类更为灵活。 漫谈 如果作为一个Python入门,不了解Python装饰器也没什么,但是如果作为一个中级Python开发人员,如果再不对python装饰器熟稔于心的话,那么可能并没有量变积累到质变。 我以前也看过很多讲python 装...

    stackvoid 评论0 收藏0
  • python装饰详解

    摘要:为了避免重复调用,可以适当地做缓存,的装饰器可以完美的完成这一任务。这意味着我们可以为方法创建装饰器,只是要记得考虑。装饰器封装了函数,这使得调试函数变得困难。另外,使用装饰器去管理缓存和权限。 原文地址 之前用python简单写了一下斐波那契数列的递归实现(如下),发现运行速度很慢。 def fib_direct(n): assert n > 0, invalid n ...

    maybe_009 评论0 收藏0

发表评论

0条评论

HackerShell

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<