美文网首页
Python修饰器

Python修饰器

作者: opluss | 来源:发表于2018-10-08 22:34 被阅读0次

前话:

python的修饰器可以说是python语言最有灵性的一个功能了,看到网上有各种乱乱的文章,所以想自己写得亲民一下,如有错误请指出。

正文:

@fnc & 被修饰函数无参数

首先看一组简单的代码:

#修饰器
def dec(fn):
    print("此处fn为函数",fn)
    return fn

@dec
#被修饰函数
def my_fn():
    return "函数返回值"

print(my_fn())
>>> 此处fn为函数 <function my_fn at 0x0000020D87993B70>
>>> 函数返回值

以上的代码的修饰过程相当于my_fn => dec(my_fn)

@fnc & 被修饰函数有参数

接下来为被修饰函数加参数:

def dec(fn):
    print("此处fn为函数",fn)
    return fn

@dec
def my_fn(a):
    return "函数返回值为"+str(a)

print(my_fn('参数'))
>>> 此处fn为函数 <function my_fn at 0x00000230F14C3B70>
>>> 函数返回值为参数

此处依然为my_fn => dec(my_fn)

[小插曲]@fnc() & 被修饰函数无/有参数

在修饰器和被修饰函数都带参数前,先准备一个小插曲:

def dec_out():
    print('运行了dec_out')
    def dec_in (b):
        print("运行了dec_in")
        return b
    return dec_in

@dec_out()
def my_fn(a):
    return "函数返回值为"+str(a)

print(my_fn('my_fn参数'))
>>> 运行了dec_out
>>> 运行了dec_in
>>> 函数返回值为my_fn参数

看到这么多函数不要晕哦,我来解释一下:

  1. 首先运行my_fn函数时先进入了修饰器
  2. 遇到了dec_out时发现修饰器位置是一个被执行的函数(带着括号),于是便执行了一下
  3. 修饰器就因为里面的return dec_in就等效成了@dec_out() => @dec_in
  4. 因此my_fn('my_fn参数')就等效成了dec_in(my_fn)('my_fn参数')

在这里休息一下,我来解答一下可能存在的疑惑:

Q:为什么上一个情况my_fn => dec(my_fn),这次是dec_in(my_fn)('my_fn参数')

A:注意细节哦,上一个是my_fn,这次是my_fn('my_fn参数')

[正餐]@fnc(*arg) & 被修饰函数无/有参数

到了正餐了,有了上一个的铺垫,这次的也可以理解了

def dec_out(a):
    print("dec_out收到了",a)
    def dec_in (b):
        print("dec_in收到了",b)
        return b
    return dec_in

@dec_out("修饰器参数")
def my_fn(a):
    return "函数返回值为"+str(a)

print(my_fn('my_fn参数'))
>>> dec_out收到了 修饰器参数
>>> dec_in收到了 <function my_fn at 0x0000022432253AE8>
>>> 函数返回值为my_fn参数

有没有预知到这次的结局呢?某种意义上很清楚明了了:

  • @dec_out("修饰器参数")在运行的因为return dec_in等效成了@dec_in,进而my_fn('my_fn参数')等效成了dec_in (my_fn)('my_fn参数')

这里我就不人肉DEBUG来给各位讲解了。

[加餐]多重@fnc(*arg) & 被修饰函数无/有参数

一下比较简单:

def dec_first(fn):
    print("dec_first运行了")
    return fn

def dec_second(fn):
    print("dec_second运行了")
    return fn

@dec_first
@dec_second
def my_fn():
    return "my_fn运行了"

print(my_fn())
>>> dec_second运行了
>>> dec_first运行了
>>> my_fn运行了

从以上可以看出修饰器的运行顺序是从临近被修饰函数开始的。但是不要认为解释器是直接从第二个修饰器开始解释的。

请看一下代码:

def dec_first_out(a):
    print("dec_first_out收到了",a)
    def dec_first_in(fn):
        print("dec_first_in运行了")
        return fn
    return dec_first_in

def dec_second(fn):
    print("dec_second运行了")
    return fn

@dec_first_out('第一个参数')
@dec_second
def my_fn():
    return "my_fn运行了"

print(my_fn())
>>> dec_first_out收到了 第一个参数
>>> dec_second运行了
>>> dec_first_in运行了
>>> my_fn运行了

由此可以看出,解释器看到了最上方的修饰器处于运行状态(有括号)于是运行,后再按上面咱们发现的行为运行。

[最后的晚餐]被修饰的修饰器

听起来复杂,实际还是这么回事:

def dec_dec(fn):
    print("dec_dec运行了")
    return fn
@dec_dec
def dec(fn):
    print("dec运行了")
    return fn

@dec
def my_fn():
    return "my_fn运行了"

print(my_fn())
>>> dec_dec运行了
>>> dec运行了
>>> my_fn运行了

看到这里应该已经清楚了吧,最有灵性的功能也是按部就班的执行的。

总结

总的来看,python的修饰器可以这么理解:

  • 如果@后方不是一个函数名称,则运行到为一个函数名称为止,这种情况才会被解释成一个 参数为被修饰函数 的函数调用过程。(这么说是为了通俗明了,实际这么说欠妥)
  • 多层的(闭包)函数作为修饰器要注意最终运行结果为一个函数名

相关文章

  • Python修饰器

    前话: python的修饰器可以说是python语言最有灵性的一个功能了,看到网上有各种乱乱的文章,所以想自己写得...

  • python修饰器

    介绍修饰器之前首先要介绍两个参数 基础用法 传递参数 *报错 这个修饰器可以简化 functools已经封装好了

  • python修饰器

    1 什么是装饰器 装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。本质就是函数,功能就...

  • python修饰器

    1、参数args与kwargs: *args是元组,如def fun(args): pass 传过去的参数是元组形...

  • python 修饰器

    python编程时首次遇到@staticmethod,就开始了我的修饰器之路 下面链接作者写的很好 https:/...

  • Python基础手册25——装饰器

    一、装饰器 装饰器背后的主要动机源自 python 面向对象编程。装饰器是在函数调用之上的修饰。这些修饰仅是当声明...

  • Python 中修饰器

    修饰器就是一个返回函数的高阶函数 如果decorator本身需要传入参数,那就需要编写一个返回decorator的...

  • 谈谈python修饰器

    前言 对python的修饰器的理解一直停留在"使用修饰器把函数注册为事件的处理程序"的层次,也是一知半解;这样拖着...

  • Python修饰器模式

    修饰器模式,可以对一个函数、类添加一层封装。

  • Python函数修饰器

    假设我们写一个小函数,打印当前的时间和一个随机整数,代码如下: 运行的结果是: 假设,我们想周期性的打印随机数,而...

网友评论

      本文标题:Python修饰器

      本文链接:https://www.haomeiwen.com/subject/xgfsaftx.html