python中的函数也是对象,函数可以被当作变量传递。

装饰器在python中功能非常强大,装饰器允许对原有函数行为进行扩展,而不用硬编码的方式,它提供了一种面向切面的访问方式。

装饰器

一个普通的装饰器一般是这样:

import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('call %s():' % func.__name__)
print('args = {}'.format(*args))
return func(*args, **kwargs)
return wrapper

这样就定义了一个打印出方法名及其参数的装饰器。
调用之:

@log
def test(p):
print(test.__name__ + " param: " + p) test("I'm a param")

输出:

call test():
args = I'm a param
test param: I'm a param

装饰器在使用时,用了@语法,让人有些困扰。其实,装饰器只是个方法,与下面的调用方式没有区别:

def test(p):
print(test.__name__ + " param: " + p) wrapper = log(test)
wrapper("I'm a param")

@语法只是将函数传入装饰器函数,并无神奇之处。
值得注意的是@functools.wraps(func),这是python提供的装饰器。它能把原函数的元信息拷贝到装饰器里面的 func 函数中。函数的元信息包括docstring、name、参数列表等等。可以尝试去除@functools.wraps(func),你会发现test.__name__的输出变成了wrapper。

带参数的装饰器

装饰器允许传入参数,一个携带了参数的装饰器将有三层函数,如下所示:

import functools

def log_with_param(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('call %s():' % func.__name__)
print('args = {}'.format(*args))
print('log_param = {}'.format(text))
return func(*args, **kwargs) return wrapper return decorator @log_with_param("param")
def test_with_param(p):
print(test_with_param.__name__)

看到这个代码是不是又有些疑问,内层的decorator函数的参数func是怎么传进去的?和上面一般的装饰器不大一样啊。
其实道理是一样的,将其@语法去除,恢复函数调用的形式一看就明白了:

# 传入装饰器的参数,并接收返回的decorator函数
decorator = log_with_param("param")
# 传入test_with_param函数
wrapper = decorator(test_with_param)
# 调用装饰器函数
wrapper("I'm a param")

输出结果与正常使用装饰器相同:

call test_with_param():
args = I'm a param
log_param = param
test_with_param

至此,装饰器这个有点费解的特性也没什么神秘了。
装饰器这一语法体现了Python中函数是第一公民,函数是对象、是变量,可以作为参数、可以是返回值,非常的灵活与强大。

原文链接:

https://www.jianshu.com/p/ee82b941772a
https://www.geeksforgeeks.org/decorators-in-python/

【Python】解析Python中的装饰器的更多相关文章

  1. Python 标准库中的装饰器

    题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...

  2. [python]在场景中理解装饰器

    原来我也自己通过查资料,来学习python的装饰器,但是效果不好.因为没有接触过需要用到装饰器的场景,所以 一起的资料都只停留在纸面上,但是今天偶然看到了vimer的这篇文章:http://www.v ...

  3. python中@property装饰器的使用

    目录 python中@property装饰器的使用 1.引出问题 2.初步改善 3.使用@property 4.解析@property 5.总结 python中@property装饰器的使用 1.引出 ...

  4. 简单说明Python中的装饰器的用法

    简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下   装饰器对与 ...

  5. Python类中的装饰器在当前类中的声明与调用

    [本文出自天外归云的博客园] 我的Python环境:3.7 在Python类里声明一个装饰器,并在这个类里调用这个装饰器.代码如下: class Test(): xx = False def __in ...

  6. 【Python】python中的装饰器——@

    对装饰器本来就一知半解的,今天终于弄清楚了,Python中的装饰器是对装饰者模式的很好运用,简化到骨子里了. python中为什么需要装饰器,看这里:http://www.cnblogs.com/hu ...

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

    Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下——比如测试时——会导致一些问题.Python 通过  ...

  8. 写python中的装饰器

    python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) def ...

  9. python中的装饰器decorator

    python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x): retur ...

  10. C#中的 Attribute 与 Python/TypeScript 中的装饰器是同个东西吗

    前言 最近成功把「前端带师」带入C#的坑(实际是前端带师开始从cocos转unity游戏开发了) 某天,「前端带师」看到这段代码后问了个问题:[这个是装饰器]? [HttpGet] public Re ...

随机推荐

  1. 《Spring Boot Cook Book》阅读笔记

    最近一个月一直在学习Spring Boot框架,在阅读<Spring Boot Cook Book>一书的过程中,记录了一些学习笔记,在这里整理出一篇目录供大家参考. 一.Spring B ...

  2. 关于ThinkPHP5.1+的Log无法记录SQL调试记录的小经历

    项目开发阶段,除了基本编码外,性能也需要实时关注与优化.之前我的大部分项目都是使用ThinkPHP5.0以及ThinkPHP3.2,对于框架提供的日志记录和日志配置都差不多,然后使用ThinkPHP5 ...

  3. anaconda更新tensorflow

    在anaconda prompt中,输入: pip install --upgrade --ignore-installed tensorflow gpu版本输入: pip install --upg ...

  4. Appium连接夜神模拟器,模拟手势点击(tap)

    # -*- coding:utf-8 -*- from appium import webdriver from time import sleep desired_caps ={ 'platform ...

  5. 《剑指Offer》-005 -用两个栈实现队列

    如题 (总结要点) 用两个栈实现队列 栈; 先进后出 队列: 先进先出 两个栈, 相等于两个杯子; 把一本水倒来倒去, 取到杯子底部的元素,并且删除,再倒回去 原文链接 : 借鉴学习文章列表 链接1: ...

  6. spring MVC核心思想

    目录  一.前言二.spring mvc 核心类与接口三.spring mvc 核心流程图 四.spring mvc DispatcherServlet说明 五.spring mvc 父子上下文的说明 ...

  7. SpringBoot整合Spring Data Elasticsearch

    Spring Data Elasticsearch提供了ElasticsearchTemplate工具类,实现了POJO与elasticsearch文档之间的映射 elasticsearch本质也是存 ...

  8. Implementing the Singleton Pattern in C#

    Table of contents (for linking purposes...) Introduction Non-thread-safe version Simple thread safet ...

  9. LeetCode 1249. Minimum Remove to Make Valid Parentheses

    原题链接在这里:https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses/ 题目: Given a string s ...

  10. MongoDB Map Reduce(转载)

    MongoDB Map Reduce Map-Reduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE). MongoDB提供的Map ...