参考链接:https://stackoverflow.com/questions/739654/how-to-make-a-chain-of-function-decorators

1. 函数对象

  • 能够赋值给其他变量
  • 能够在另外函数内定义
  • 能够作为参数进行传递
  • 能够作为函数的返回值
def firstLevel(f_arg):  # 作为参数,可以赋值
def tmp_func(*args, **kwargs): # 可以在另外函数内定义
# do something ...
ret = f_arg(*args, **kwargs)
# do something ...
return ret
return tmp_func # 作为函数的返回值 # 1. 原始方法
def func(*args, **kwargs):
print("In func")
func = firstLevel(func) # 2. 装饰器方法
@firstLevel
def func(*args, **kwargs):
print("In func") # 使用
func()

2. 多层装饰器

可以对函数进行一层又一层的包装,使用多层装饰器即可

def firstLevel(f_arg):
def tmp_func(*args, **kwargs):
print("----s.firstLevel----")
ret = f_arg(*args, **kwargs)
print("----e.firstLevel----")
return ret
return tmp_func def secondLevel(f_arg):
def tmp_func(*args, **kwargs):
print("----s.secondLevel----")
ret = f_arg(*args, **kwargs)
print("----e.secondLevel----")
return ret
return tmp_func #1. 原始方法
def func(*args, **kwargs):
print("In func")
func = firstLevel(secondLevel(func))
func() # 2. 装饰器方法
@firstLevel
@secondLevel
def func(*args, **kwargs):
print("In func")
func()

@firstLevel 语法,

这个后面看似隐藏了一对(),用来将下面的代码作为装饰器函数返回的内部函数的参数进行传递,当明确指定()的时候,则是给装饰器函数传递参数,

3. 装饰器接收参数

@firstLevel 语法,告诉我们这个函数接收的参数是一个函数对象,内部返回的是一个函数(firstLevel就是函数名,使用@标记告诉我们的)

@firstLevel(arg1, arg2, ...) 语法,告诉我们这个firstLevel(arg1, arg2, ...) 函数接收参数,返回的也是一个函数,返回的函数比如叫 retLevel,则将转化为: @retLevel 语法,retLevel 语法就跟上面的语法一样,告诉我们返回的 retLevel 接收的参数是一个函数对象,内部同样返回了一个函数 (retLevel 就是中间函数名,使用@标记告诉我们的)

def firstLevel(arg1, arg2):
# do something ...
print(arg1, arg2)
# 使用参数做一些事情(这是函数传递参数的目的)
def tmpRetLevel(f_arg):
def tmp_func(*args, **kwargs):
# do something ...
ret = f_arg(*args, **kwargs)
# do something ...
return ret
return tmp_func return tmpRetLevel # 1. 原始方法
def func(*args, **kwargs):
print("In func") retLevel = firstLevel('', '')
func = retLevel(func)
func('', '') # 2. 装饰器方法
@firstLevel('', '')
def func(*args, **kwargs):
print("In func") func('', '')

4. functools实现装饰器

上面的返回后的函数,打印一些内部变量比如:func.__doc__, __name__ 将变为 内部函数的 __doc__,__name__ 描述信息,functools.wraps将解决这样的问题,wraps()函数本身就是一个装饰器。

import functools

def firstLevel(f_arg):
@functools.wraps(f_arg):
def tmpFunc(*args, **kwargs):
# do something ...
ret = f_arg(*args, **kwargs)
# do something ...
return ret
return tmpFunc @firstLevel
def func(*args, **kwargs):
print("In func") print(func.__name__) # 输出:func

4. 使用场景

  • 装饰外部提供的库
  • 避免大量重复代码的编写
  • 比如:Django对视图的权限控制,Twisted将函数修改为异步调用

[TimLinux] Python 再谈装饰器的更多相关文章

  1. python再议装饰器

    装饰器实质还是一个函数,是对其他函数进行装饰的函数.装饰器函数接受被装饰函数的函数名,返回被装饰函数的函数名.对一个函数进行装饰有两个原则:一是不能修改被装饰函数的源代码:二是被装饰函数的调用方式不可 ...

  2. [TimLinux] Python 再谈元类 metaclass

    本博文通过对以下链接进行理解后,编写. https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python 1. 类 类 ...

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

    hello大家好~~我是稀里糊涂林老冷,一天天稀里糊涂的. 前一段时间学习了装饰器,觉着这东西好高大上哇靠!!哈哈,一定要总结一下,方便以后自己查阅,也希望帮助其他伙伴们共同进步! 装饰器: 大家可以 ...

  4. python之路——装饰器函数

    阅读目录 楔子 装饰器的形成过程 开放封闭原则 谈装饰器主要功能和装饰器固定结构 带参数的装饰器 多个装饰器装饰一个函数 返回顶部 楔子 作为一个会写函数的python开发,我们从今天开始要去公司上班 ...

  5. python之路---装饰器函数

    阅读目录 楔子 装饰器的形成过程 开放封闭原则 谈装饰器主要功能和装饰器固定结构 带参数的装饰器 多个装饰器装饰一个函数 返回顶部 楔子 作为一个会写函数的python开发,我们从今天开始要去公司上班 ...

  6. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  7. Day04 - Python 迭代器、装饰器、软件开发规范

    1. 列表生成式 实现对列表中每个数值都加一 第一种,使用for循环,取列表中的值,值加一后,添加到一空列表中,并将新列表赋值给原列表 >>> a = [0, 1, 2, 3, 4, ...

  8. Noah的学习笔记之Python篇:装饰器

    Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) ...

  9. 第二篇:python高级之装饰器

    python高级之装饰器   python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...

随机推荐

  1. 实现 sqrt(x):二分查找法和牛顿法

    最近忙里偷闲,每天刷一道 LeetCode 的简单题保持手感,发现简单题虽然很容易 AC,但若去了解其所有的解法,也可学习到不少新的知识点,扩展知识的广度. 创作本文的思路来源于:LeetCode P ...

  2. Python 面向对象之五 基础拾遗

    Python 面向对象之五 基础拾遗 今天呢,就剩下的面向对象的相关知识进行学习,主要会学习以下几个方面的知识:1.上下文管理协议,2.为类加装饰器 3.元类 一.上下文管理协议 在学习文件操作的时候 ...

  3. Java升级那么快,多个版本如何灵活切换和管理?

    前言 近两年,Java 版本升级频繁,感觉刚刚掌握 Java8,写本文时,已听到 java14 的消息,无论是尝鲜新特性(Java12 中 Collectors.teeing 超强功能使用),还是由于 ...

  4. [java] 集合的架构——1张图表示

  5. SpringBoot 源码解析 (五)----- Spring Boot的核心能力 - 自动配置源码解析

    在上一篇博客中分析了springBoot启动流程,大体的轮廓只是冰山一角.今天就来看一下springBoot的亮点功能:自动化装配功能. 先从@SpringBootApplication开始.在启动流 ...

  6. (C#)WPF:关于INotifyPropertyChanged接口的介绍

    注意:INotifyPropertyChanged接口位于System.CompenentModel名称空间中,想使用INotifyPropertyChanged接口时,头文件需添加“using Sy ...

  7. 最省钱的爬虫解决方案,比IP代理更划算

    现状: 1.网上提供代理IP池的解决方案非常多,价格也有高有低,包天/月/年的都有,品质都要靠自己去尝试. 2.试过之后,发现成本相对高,每月要花200~300元, 所以希望研究一下是否有更性价比高的 ...

  8. Java多线程——对象及变量的并发访问

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

  9. Rocket框架多文件上传,介绍rocket_upload 使用

    不知道你的体会是什么,我从C切换到Rust以来,最大的感受并不是语法方面的---那些方面已经有足够多人抱怨而又享受着了.我最大的感受是终于把Web编程工具,同系统编程工具统一了起来. C/C++其实也 ...

  10. Java中代理和装饰者模式的区别

    装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案: 代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用: 装饰模式为所装饰的对象增强功能:代理模式对代理的对 ...