Python 装饰器原理、定义与用法详解


Posted in Python onDecember 07, 2019

本文实例讲述了Python 装饰器原理、定义与用法。分享给大家供大家参考,具体如下:

Python 装饰器

一、何为装饰器

1、在函数中定义函数

在函数中定义另外的函数,就是说可以创建嵌套的函数,例子如下

def sayHi(name="hjj2"):
 print 'inside sayHi() func'
 def greet():
  return 'inside greet() func'
 print(greet())
sayHi()
#output
#  inside sayHi() func
#  inside greet() func

2、将函数作为参数传给另外一个函数,装饰器原型

def sayHi():
 return 'hi hjj2'
def doSthBeforeSayHi(func):
 print 'before sayHi func'
 print(func())
doSthBeforeSayHi(sayHi)
#output
#  before sayHi func
#  hi hjj2

3、实现一个装饰器

在第二步中,我们已经基本探究到装饰器的原理了,python装饰器做的事就是通过封装一个函数并且用这样或那样的方式来修改它的行为。不带@的初步示例如下:

def new_decorator(func):
  def wrapDecorator():
   print 'before func'
   func()
   print 'after func'
  return wrapDecorator
def func_require_decorator():
  print 'a func need decorator'
func_require_decorator()
#ouput: a func need decorator
func_require_decorator = new_decorator(func_require_decorator)
func_require_decorator()
#ouput:
#  before func
#  a func need decorator
#  after func

使用@来运行装饰器

@new_decorator
func_require_decorator()
#ouput:
#  before func
#  a func need decorator
#  after func

这里我们可以看到,这两个例子的运行结果是一样的。所以我们能想象得到@new_decorator的作用就是

func_require_decorator = new_decorator(func_require_decorator)

我们继续优化这个装饰器,现在我们有一个问题就是,如果我们想要通过print(func_require_decorator.__name__)就会报错# Output: wrapTheFunction。这样就需要借助python提供的functools.wraps来解决了

@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

from functools import wraps
def new_decorator(func):
  @wraps(func)
  def wrapDecorator():
   print 'before func'
   func()
   print 'after func'
  return wrapDecorator
def func_require_decorator():
  print 'a func need decorator'
@new_decorator
func_require_decorator()
print(func_require_decorator.__name__)
#ouput: func_require_decorator

二、使用场景

1、授权,大体例子

from functools import wraps
def requires_auth(f):
  @wraps(f)
  def decorated(*args, **kwargs):
    auth = request.authorization
    if not auth or not check_auth(auth.username, auth.password):
      authenticate()
    return f(*args, **kwargs)
  return decorated

2、日志:

from functools import wraps
def logit(logfile='out.log'):
  def logging_decorator(func):
    @wraps(func)
    def wrapped_function(*args,**kwargs):
      log_string = func.__name__+"was called"
      print(log_string)
      with open(logfile,'a') as opened_file:
        opened_file.write(log_string+'\n')
      return func(*args,**kwargs)
    return wrapped_function
  return logging_decorator
@logit()
def func1():
  pass
func1()

3、其他如flask中的@app.route()

三、装饰器类

1、将上面的日志装饰器变为类的初步模型如下

from functools import wraps
class logit(object):
  def __init__(self, logfile='out.log'):
    self.logfile = logfile
  def __call__(self, func):
    @wraps(func)
    def wrapped_function(*args, **kwargs):
      log_string = func.__name__ + "was called"
      print(log_string)
      # 打开logfile并写入
      with open(self.logfile, 'a') as open_file:
        # 将日志写到指定文件
        open_file.write(log_string + '\n')
      # 发送一个通知
      self.notify()
      return func(*args, **kwargs)
    return wrapped_function
  def notify(self):
    pass
@logit()
def myfunc1():
  pass
class email_logit(logit):
  '''
  实现在函数调用时发送email
  '''
  def __init__(self, email='admin@xxx.com', *args, **kwargs):
    self.email = email
    super(email_logit, self).__init__(*args, **kwargs)
  def notify(self):
    '''
    发送邮件通知
    '''
    pass

通过这种方式,我们可以定义我们在自己的需求,减少代码的冗余,提高复用率。

至此,关于装饰器的探索就结束啦。

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
python实现淘宝秒杀聚划算抢购自动提醒源码
Jun 23 Python
对python的bytes类型数据split分割切片方法
Dec 04 Python
Python3.0中普通方法、类方法和静态方法的比较
May 03 Python
使用python打印十行杨辉三角过程详解
Jul 10 Python
django用户登录验证的完整示例代码
Jul 21 Python
centos7之Python3.74安装教程
Aug 15 Python
使用python绘制cdf的多种实现方法
Feb 25 Python
python实现TCP文件传输
Mar 20 Python
django rest framework使用django-filter用法
Jul 15 Python
cookies应对python反爬虫知识点详解
Nov 25 Python
python如何获取网络数据
Apr 11 Python
pytorch查看网络参数显存占用量等操作
May 12 Python
Python Pandas 转换unix时间戳方式
Dec 07 #Python
Pandas-Cookbook 时间戳处理方式
Dec 07 #Python
Python数据可视化:饼状图的实例讲解
Dec 07 #Python
Python数据可视化:幂律分布实例详解
Dec 07 #Python
Python数据可视化:泊松分布详解
Dec 07 #Python
python-numpy-指数分布实例详解
Dec 07 #Python
Python Sympy计算梯度、散度和旋度的实例
Dec 06 #Python
You might like
PHPMyAdmin 快速配置方法
2009/05/11 PHP
利用php-cli和任务计划实现订单同步功能的方法
2017/05/03 PHP
phpstudy2020搭建站点的实现示例
2020/10/30 PHP
Javascript读取cookie函数代码
2010/10/16 Javascript
jquery 单击li防止重复加载的实现代码
2010/12/24 Javascript
无缝滚动js代码通俗易懂(自写)
2013/06/19 Javascript
PHP abstract与interface之间的区别
2013/11/11 Javascript
使用JSON.parse将json字符串转换成json对象的时候会出错
2014/09/04 Javascript
JS组件系列之Bootstrap table表格组件神器【终结篇】
2016/05/10 Javascript
js带闹铃功能的倒计时代码
2016/09/29 Javascript
ES6新特性之字符串的扩展实例分析
2017/04/01 Javascript
纯JS实现图片验证码功能并兼容IE6-8(推荐)
2017/04/19 Javascript
vue使用iframe嵌入网页的示例代码
2020/06/09 Javascript
vue项目引入字体.ttf的方法
2018/09/28 Javascript
angular4笔记系列之内置指令小结
2018/11/09 Javascript
小程序开发中如何使用async-await并封装公共异步请求的方法
2019/01/20 Javascript
jQuery实现每日秒杀商品倒计时功能
2019/09/06 jQuery
Vue 3.0 全家桶抢先体验
2020/04/28 Javascript
vue实现页面切换滑动效果
2020/06/29 Javascript
[07:20]2018DOTA2国际邀请赛寻真——逐梦Mineski
2018/08/10 DOTA
phpsir 开发 一个检测百度关键字网站排名的python 程序
2009/09/17 Python
简析Python的闭包和装饰器
2016/02/26 Python
python批量添加zabbix Screens的两个脚本分享
2017/01/16 Python
Python操作mongodb数据库进行模糊查询操作示例
2018/06/09 Python
python中的decimal类型转换实例详解
2019/06/26 Python
PowerBI和Python关于数据分析的对比
2019/07/11 Python
Django 实现图片上传和显示过程详解
2019/07/18 Python
调试Django时打印SQL语句的日志代码实例
2019/09/12 Python
python sorted函数原理解析及练习
2020/02/10 Python
欧洲第一的摇滚和金属乐队服装网站:EMP
2017/10/26 全球购物
合作合同协议书范本
2015/01/27 职场文书
企业爱心捐款倡议书
2015/04/27 职场文书
2016年公共机构节能宣传周活动总结
2016/04/05 职场文书
python实现调用摄像头并拍照发邮箱
2021/04/27 Python
JavaScript实例 ODO List分析
2022/01/22 Javascript
Ruby处理CSV数据方法详解
2022/04/18 Ruby