Python 装饰器详解

Python 装饰器详解

  装饰器(Decorators)是 Python 的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短。大多数初学者不知道在哪儿使用它们,所以我将要分享下,哪些区域里装饰器可以让你的代码更简洁。 首先,让我们讨论下如何写你自己的装饰器。
  这可能是最难掌握的概念之一。我们会每次只讨论一个步骤,这样你能完全理解它。
装饰器让你在一个函数的前后去执行代码
在大家学习装饰器之前,大家应该掌握函数的用法,特别是闭包,如果大家还不熟悉,可以看Python函数详解这篇文章

你的第一个装饰器

程序示例:

"""
我的第一个装饰器
version:1.0
writer:假书生@
date:2020.02.09
"""
def Outer(func):     #定义外层函数
    def Inner():     #定义内层函数
        print("执行func()前")
        func()      #执行参数所传进来的函数
        print("执行func()后")
    return  Inner

def Hello():

    print("Hello,world")
Outer(Hello)()    # 调用外层函数,传参
# a = Outer(Hello)
# a()

运行结果:

执行func()前
Hello,world
执行func()
我们刚刚应用了之前学习到的原理。这正是 python 中装饰器做的事情!它们封装一个函数,并且用这样或者那样的方式来修改它的行为。现在你也许疑惑,我们在代码里并没有使用 @ 符号?那只是一个简短的方式来生成一个被装饰的函数。这里是我们如何使用 @ 来运行之前的代码:

程序示例:

"""
我的第二个装饰器
version:1.0
writer:假书生@
date:2020.02.09
"""
def Outer(func):     #定义外层函数
    def Inner():     #定义内层函数
        print("执行func()前")
        func()      #执行参数所传进来的函数
        print("执行func()后")
    return  Inner
@Outer
def Hello():
    print("Hello,world")
Hello()
运行结果:
执行func()前
Hello,world
执行func()
但是,如果我们运行如下代码会存在一个问题:
print(Hello.__name__)
Inner
这并不是我们想要的!Ouput输出应该是"Hello"。这里的函数被Inner替代了。它重写了我们函数的名字和注释文档(docstring)。幸运的是Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。我们修改上一个例子来使用functools.wraps:

程序示例:

"""
我的第二个装饰器
version:1.0
writer:假书生@
date:2020.02.09
"""
from functools import wraps
def Outer(func):     #定义外层函数
    @wraps(func)
    def Inner():     #定义内层函数
        print("执行func()前")
        func()      #执行参数所传进来的函数
        print("执行func()后")
    return  Inner
@Outer
def Hello():
    print("Hello,world")
Hello()
print(Hello.__name__)

运行结果:

执行func()前
Hello,world
执行func()后
Hello
下面给大家介绍一下装饰器的通用写法

程序示例:

"""
我的第三个装饰器
version:1.0
writer:假书生@
date:2020.02.09
"""
from functools import wraps
def Outer(func):     #定义外层函数
    @wraps(func)
    def Inner(*args,**kwargs):     #定义内层函数
        if  not can_run:

            return "这个函数不能执行"
        print("这个函数可以执行")
        return func(*args,**kwargs)      #执行参数所传进来的函数
    return  Inner

@Outer
def Hello():
    print("Hello,world")
can_run = False
print(Hello())
# can_run  = True
Hello()

运行结果:

这个函数不能执行
#这个函数可以执行
#Hello,world

使用场景

授权

装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。它们被大量使用于Flask和Django web框架中。这里是一个例子来使用基于装饰器的授权:
def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization    #认证
        if not auth or not check_auth(auth.username, auth.password):  # 如果没有认证,或者用户名、密码不正确
            authenticate()         #执行认证函数
        return f(*args, **kwargs)
    return decorated

日志

日志是装饰器运用的另一个亮点。就是在执行函数的时候将这个过程记录在日志:
from functools import wraps
 
def logit(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging
@logit
def addition_func(x):
   """Do some math."""
   return x + x
result = addition_func(4)

带参数的装饰器类

程序示例:

"""
"""
我的第四个装饰器
version:1.0
writer:假书生@
date:2020.02.09
"""
from functools import  wraps
def Logi(files = 'log.txt'):   #传入日志参数
    def Outer(func): 
        @wraps(func)  
        def Inner(*args,**kwargs):
            str = func.__name__ + "is called"   #写入日志文件的内容
            with open (files,'a') as file:      #打开日志文件
                file.write(str+'\n')            #在日志文件中写入内容
            return func(*args,**kwargs)     
        return Inner
    return Outer
@Logi()
def Hello():
    print("Hello,world,")
Hello()

运行结果:

Hellois called
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值