当前位置: 首页 > news >正文

python decorators_Python进阶之强大的装饰器 Decorators (一)

这篇文章主要介绍 decorator(装饰器),在开始介绍 decorator 前,要先有一个观念,就是在 python 中,函数是对象,可以将它们分配给变量和传递给其他函数并从其他函数返回,可以在其他函数中定义函数,并且子功能可以捕获父功能的本地状态。

demo1.py

def f1():

print("f1")

def register(func):

func()

register(f1)

装饰器就是站在这个基础上去延伸出来的。接著来说说什麽时候要用装饰器,装饰器最主要的目的是在不破坏 function(函数) 或 class(类) 的情况下,去扩充目标 function 或 class 的功能。例如,logging、计算 function or class 执行的时间、权限等等。

如果大家有兴趣,可以再去查查 AOP ( Aspect Oriented Programming ),中文翻成 面向切面。

有了这个装饰器,我们就可以将大量的程式码抽出来( 与函数本身无关的部分 ),将这些 code 写到装饰器中 ( 可以重复使用 ),程式码也不会变得很乱。

说穿了,就是在现在的功能上,可以加上额外的功能 ( 重点是不破坏原有的 code )。

举个例子,今天我想要记录 f1() 的 logging,我们可能这样写,

(正常来说,应该要使用 logging 这个 module,但这边简单用 print 代替就好 😄)

def f1():

print("f1")

print("logging - f1 is running")

f1()

这样写看似没有问题,但如果你今天 f2() f3() f4() 都需要纪录呢 ❓

这样要每一个都写一样的 code ❓

我们能不能把它抽出来 ❓ 而这个东西,就是专门处理 logging 的,

答案当然是可以的😄

def my_logging(func):

print('logging - {} is running'.format(func.__name__))

func()

def f1():

print("f1")

my_logging(f1)

功能实现了,看似很美好,如果有其他的需要加上 logging,使用 my_logging(f2) 即可。但这方法其实有一些问题,问题点在每次都要呼叫 my_logging,而且也要将 f1 当成参数传递,比较好的方法应该是维持 f1 为主要业务逻辑,而不是像现在变成 my_logging 为主要业务逻辑,也就是说,现在的状况破坏了原有代码的结构。所以更好的方法,就是使用装饰器 ( 我们终于谈到主角了😄),来看一个简单的装饰器。

def my_logging(func):

def wrapper():

print('logging - {} is running'.format(func.__name__))

func() # run func() Equivalent run f1()

return wrapper

def f1():

print("f1")

f1 = my_logging(f1) # Equivalent -> f1 = wrapper

f1() # Equivalent -> f1() = wrapper()

my_logging 就是一个装饰器,把真正的业务逻辑 func 包在里面,看起来就像是 func 被 my_logging 装饰了一样,所以顾名思义,称为装饰器。在这个范例中,函数的进入和退出时,都可以加上东西,这种方式也称为 AOP ( Aspect Oriented Programming )。接下来要来谈谈 @ 这个符号,你可以把他想成是一种语法的符号。

def my_logging(func):

def wrapper():

print('logging - {} is running'.format(func.__name__))

func() # run func() Equivalent run f1()

return wrapper

@my_logging

def f1():

print("f1")

f1()

当有了 @ 这个语法的帮忙,就可以将 f1 = my_logging(f1) 省略,直接使用 f1() 即可。

相关文章:

  • 设备能力指数cmk计算公式_拧紧微课堂|关于CM,CMK,CP,CPK
  • sql 转置_SQL -- 练习汇总
  • python语言中打印到屏幕上的函数是什么_Python基础之白话说函数
  • 概率论与数理统计思维导图_2020年基础考试高等数学思维导图
  • 用python画圆角矩形_如何用OpenCV绘制圆角矩形(带圆角的矩形)?
  • vfp控制excel选择全表_Excel快速填充功能,让你输入数据不只是快一点点
  • 遍历list 分组求和_LeetCode刷题实战49:字母异位词分组
  • spark labeledpoint函数用法_Hive常用的函数总结
  • python字符串子串替换方法_python替换字符串中的子串图文步骤
  • 多选框位置调整_水下目标检测竞赛冠军方案:多图像融合增强 | URPC 2019
  • unexpected eof while parsing什么意思_少侠留步!你知道if、while和递归之间的关系吗?...
  • python batch normalization_使用Python实现Batch normalization和卷积层
  • python 模糊匹配库_Python中实现模糊匹配的魔法库:FuzzyWuzzy
  • apache ii评分怎么评_雅思分数怎么算?评分标准了解下
  • 百度搜索接口api_搜索推广丨oCPC投放API接入方式详解
  • @jsonView过滤属性
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • eclipse(luna)创建web工程
  • HTML中设置input等文本框为不可操作
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • js
  • js面向对象
  • log4j2输出到kafka
  • Node + FFmpeg 实现Canvas动画导出视频
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • Phpstorm怎样批量删除空行?
  • Promise面试题,控制异步流程
  • spring cloud gateway 源码解析(4)跨域问题处理
  • Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比...
  • Vue 重置组件到初始状态
  • 讲清楚之javascript作用域
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 聊聊sentinel的DegradeSlot
  • 前嗅ForeSpider采集配置界面介绍
  • 使用权重正则化较少模型过拟合
  • 探索 JS 中的模块化
  • 新手搭建网站的主要流程
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 再次简单明了总结flex布局,一看就懂...
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • 如何在招聘中考核.NET架构师
  • #宝哥教你#查看jquery绑定的事件函数
  • #每天一道面试题# 什么是MySQL的回表查询
  • #我与Java虚拟机的故事#连载19:等我技术变强了,我会去看你的 ​
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (C语言)fread与fwrite详解
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (差分)胡桃爱原石
  • (超详细)语音信号处理之特征提取
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式