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使用urlparse分析网址中域名的方法
Apr 15 Python
python查看zip包中文件及大小的方法
Jul 09 Python
Python正则表达式使用范例分享
Dec 04 Python
Python实现列表删除重复元素的三种常用方法分析
Nov 24 Python
Python实现嵌套列表去重方法示例
Dec 28 Python
python实现趣味图片字符化
Apr 30 Python
详解Python字符串切片
May 20 Python
python 求定积分和不定积分示例
Nov 20 Python
python3实现绘制二维点图
Dec 04 Python
python单元测试框架pytest的使用示例
Oct 07 Python
使用tensorflow 实现反向传播求导
May 26 Python
numpy array找出符合条件的数并赋值的示例代码
Jun 01 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
dedecms 制作模板中使用的全局标记图文教程
2007/03/11 PHP
php增删改查示例自己写的demo
2013/09/04 PHP
php中socket通信机制实例详解
2015/01/03 PHP
PHP如何实现跨域
2016/05/30 PHP
PHP对称加密函数实现数据的加密解密
2016/10/27 PHP
Laravel框架路由管理简单示例
2019/05/07 PHP
php统计数组不同元素的个数的实例方法
2019/09/26 PHP
Javascript 强制类型转换函数
2009/05/17 Javascript
理解Javascript_05_原型继承原理
2010/10/13 Javascript
基于jquery的用鼠标画出可移动的div
2012/09/06 Javascript
JS小功能(button选择颜色)简单实例
2013/11/29 Javascript
jQuery的ready方法详解
2014/11/27 Javascript
jQuery实现类似淘宝网图片放大效果的方法
2015/07/08 Javascript
jquery动态导航插件dynamicNav用法实例分析
2015/09/06 Javascript
JavaScript+canvas实现七色板效果实例
2016/02/18 Javascript
js前端实现多图图片上传预览的两个方法(推荐)
2016/11/18 Javascript
canvas实现弧形可拖动进度条效果
2017/05/11 Javascript
Vue基于NUXT的SSR详解
2017/10/24 Javascript
vue-cli3 karma单元测试的实现
2019/01/18 Javascript
JavaScript中EventBus实现对象之间通信
2020/10/18 Javascript
python3抓取中文网页的方法
2015/07/28 Python
Python判断两个list是否是父子集关系的实例
2018/05/04 Python
tensorflow实现图像的裁剪和填充方法
2018/07/27 Python
利用Python模拟登录pastebin.com的实现方法
2019/07/12 Python
django settings.py 配置文件及介绍
2019/07/15 Python
Python使用socketServer包搭建简易服务器过程详解
2020/06/12 Python
解决pip install psycopg2出错问题
2020/07/09 Python
Python编写memcached启动脚本代码实例
2020/08/14 Python
Python读取pdf表格写入excel的方法
2021/01/22 Python
html5构建触屏网站之touch事件介绍
2013/01/07 HTML / CSS
产品质量承诺书
2014/03/27 职场文书
师范生免费教育协议书范本
2014/10/09 职场文书
师德标兵先进事迹材料
2014/12/19 职场文书
演讲比赛主持词
2015/06/29 职场文书
《半截蜡烛》教学反思
2016/02/19 职场文书
python缺失值填充方法示例代码
2022/12/24 Python