如何理解python中的装饰器, 这篇文章就够了!

1. python中的函数

  • 理解裝飾器之前先要理解閉包, python中閉包的出現是因爲函數在python中也是一個對象, 也可以被引用, 然後調用, 比如
def log():
    print(‘我是一些log信息‘)

if __name__ == ‘__main__‘:
    print(type(log))
    log_func = log
    log_func()
  • 執行結果如下
<class ‘function‘>
我是一些log信息
  • 可以看到log函數是一個對象, 可以被賦值給log_func, log_func可以像函數一樣被執行

2. python中的闭包

  • 理解了python也是一個函數, 我們看看閉包, 閉包就是函數裏面返回了一個函數, 第二層嵌套函數還可以引用第一層函數的局部變量, 相當於嵌套函数引用了这个变量,将这个局部变量封闭在了嵌套函数中, 這樣的結構叫做閉包, 比如
def log():
    log_info = ‘我是一些log信息‘

    def wrapper():
        print(log_info)
        print(‘我是函數wrapper實現的功能‘)

    return wrapper

if __name__ == ‘__main__‘:
    f = log()()
  • 函数log()执行结果是一个wrapper函数对象, log()后面再加一个()调用就是wapper函数, 返回打印结果如下:
我是一些log信息
我是函數wrapper實現的功能

3. python中的装饰器

  • 理解了闭包, 我们看看装饰器, 装饰器可以看成一个"自动"帮我们执行的闭包, 它的作用是能帮我们的函数或者类在不改变原有功能代码的前提下额外增加一些功能
import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print(‘name参数是: {}‘.format(*args))
        print(‘我在函数%s()被调用前做了一些事情‘ % func.__name__)
        print(‘调用函数 %s():‘ % func.__name__)
        return func(*args, **kwargs)

    return wrapper

@log
def get_user_info(name):
    print(‘函数{}的执行结果是: 获取到用户{}的信息‘.format(get_user_info.__name__, name))

if __name__ == ‘__main__‘:
    get_user_info(‘XiaoMing‘)

  • 执行结果如下:
name参数是: XiaoMing
我在函数get_user_info()被调用前做了一些事情
调用函数 get_user_info():
函数get_user_info的执行结果是: 获取到用户XiaoMing的信息
  • log函数是一个闭包, 传入的参数是一个函数, 并且函数的参数被一层层嵌套函数传递下去
  • @语法帮我们做的事情就是"自动"执行这个闭包函数到最后一层, 也就是到wrapper函数这一层, 相当于是

    get_user_info = log(get_user_info(‘XiaoMing‘))()

  • 当我们调用get_user_info函数时候, 我们并不是调用我们写的函数, 而是log闭包函数里面的wrapper函数, 然后wrapper的返回结果会真正调用我们写的get_user_info函数
  • @functools.wraps(func)这段代码的意思就是将原函数get_user_info的元信息(docstring、name、参数列表)拷贝到装饰器里面的wrapper函数中
  • 这样@log这个装饰器就帮我们实现了在不改变原有代码的基础上额外增加了get_user_info这个函数的功能

原文地址:https://www.cnblogs.com/iread9527/p/12549205.html

时间: 2024-10-25 02:08:19

如何理解python中的装饰器, 这篇文章就够了!的相关文章

理解Python中的装饰器

文章先由stackoverflow上面的一个问题引起吧,如果使用如下的代码: @makebold @makeitalic def say(): return "Hello" 打印出如下的输出: <b><i>Hello<i></b> 你会怎么做?最后给出的答案是: def makebold(fn): def wrapped(): return "<b>" + fn() + "</b>&q

@修饰符--python中的装饰器

http://blog.csdn.net/shangzhihaohao/article/details/6928808 装饰器模式可以在不影响其他对象的情况下,以动态.透明的方式给单个对象添加职责,也能够处理那些可以撤销的职责.经常用于日志记录.性能测试等场合. 想象一下这个很常见的场景,你写了一个方法只提供给以登陆的用户访问(事实上我也是通过django的@login_required才了解到@修饰符的),你可以写以下代码: 这当然没什么问题,但是你又写了一个方法B,也要求只有登录用户可以访问

Python 中实现装饰器时使用 @functools.wraps 的理由

Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下--比如测试时--会导致一些问题.Python 通过 functool.wraps 为我们解决了这个问题:在编写装饰器时,在实现前加入 @functools.wraps(func) 可以保证装饰器不会对被装饰函数造成影响.比如,在 Flask 中,我们要自己重写 login_required 装饰器,但不想影响被装饰器装饰的方法,则 login_req

浅显易懂的谈一谈python中的装饰器!!

hello大家好~~我是稀里糊涂林老冷,一天天稀里糊涂的. 前一段时间学习了装饰器,觉着这东西好高大上哇靠!!哈哈,一定要总结一下,方便以后自己查阅,也希望帮助其他伙伴们共同进步! 装饰器: 大家可以这样理解,装饰器是运用闭包的基本原理,对一个目标函数进行装饰.即是在执行一个目标函数之前.之后执行一些特定的事情. 学习装饰器一定要有闭包的基础知识,如果对闭包不是特别理解的话,可以参考我之前的博文http://www.cnblogs.com/Lin-Yi/p/7305364.html,也可以学习其

Python 中的装饰器

说到装饰器是我们每个学Python人中的心痛. 装饰器作用:是用来装饰其他函数的,为其他函数添加新功能. 原则:1.不能改变被修饰函数的源代码. 2.不能修改被修饰函数的调用方式. 学装饰器前还需要了解的东西: 返回值(return): return 语句是可选的,它可以定义在函数体的任意位置表示函数调用到此结束.如果没有return语句输出的是none,如果有return语句但是return后没有跟东西,也是返回的是none. 注意:(1)要想看到return后边的值,需要打印出来print(

Python中的装饰器

假定现有如下需求: 已经定义了一个函数,想在运行时动态增加其功能,又不想改动函数本身的代码.应该如何实现呢? 比如现在定义了f1函数如下: def f1(x): return x*2 print f1(5) 那么,现在想加入一个打印日志的方法,打印出调用的是哪个方法的方法.一般做法是这样: def f1(x): print 'call f1()' return x*2 print f1(5) 那有没有更简单明了的方法呢,我上篇博文中有写的高阶函数,那么我们想到高阶函数是可以把函数当参数并且可以返

python cookbook 学习系列(一) python中的装饰器

简介 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓存.权限校验等场景.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能,我们也称之为AOP(面向切面编程) 原理 实现装饰器的最主要的原因是python中一切皆为对象,我们会把方法看做一个对

python中初级装饰器总结

打印 args 与 *args 的区别 1 #打印时区别 2 def outer(*args, **kwargs): 3 print(args) #输出结果:(1, 2, 3, 4) 4 print(*args) #输出结果:1 2 3 4 5 6 outer(1,2,3,4) 1 #函数调用时区别 2 def outer(*args, **kwargs): 3 print(args) 4 print(*args) #也是调用函数,调用的是print函数 5 6 outer([1,2,3,4])

[python基础]关于装饰器

在面试的时候,被问到装饰器,在用的最多的时候就@classmethod ,@staticmethod,开口胡乱回答想这和C#的static public 关键字是不是一样的,等面试回来一看,哇,原来是这样,真佩服我当时厚着脸皮回答的那些问题... OK,先来张图看看装饰器内容: OK,我们留下一个印象,然后我们看实际的场景来操作. 我们先看一个方法: __author__ = 'bruce' def do_sth(): print 'some thing has been done' if __