1.python装饰器的缺点

装饰器可以允许我们在不改变函数或犯方法的调用方式的情况下,添加额外的功能;

如下所示,我们要在中的方法之前增加装饰器check_is_admin,用来判断执行类的方法的用户是否为admin用户;

def check_is_admin(f):
def wrapper(*args,**kwargs):
if kwargs.get('username') != 'admin':
raise Exception("This user is not allowed to get food")
return f(*args,**kwargs)
return wrapper class store(object):
@check_is_admin
def get_food(self,username,food):
return self.storage.get(food) @check_is_admin
def put_food(self,username,food):
self.storage.put(food)

但是,经过装饰器修饰的函数,其func_name和func_doc的属性都会丢失;

如下:

def foobar(username="someone"):
"""Do crzay staff."""
pass
print foobar.func_doc
print foobar.func_name 执行结果为:
Do crzay staff.
foobar

如果给上述函数增加装饰器呢?

def is_admin(f):
def wrapper(*args,**kwargs):
if kwargs.get(*args,**kwargs):
raise Exception("This user is not allowed to get food")
return f(*args,**kwargs)
return wrapper @is_admin
def foobar(username="someone"):
"""Do crazy staff"""
pass
print foobar.__doc__
print foobar.__name__ 执行结果为:
None
wrapper

update_wapper的源码如下:

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
WRAPPER_UPDATES = ('__dict__',)
def update_wrapper(wrapper,
wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
"""Update a wrapper function to look like the wrapped function wrapper is the function to be updated
wrapped is the original function
assigned is a tuple naming the attributes assigned directly
from the wrapped function to the wrapper function (defaults to
functools.WRAPPER_ASSIGNMENTS)
updated is a tuple naming the attributes of the wrapper that
are updated with the corresponding attribute from the wrapped
function (defaults to functools.WRAPPER_UPDATES)
"""
for attr in assigned:
setattr(wrapper, attr, getattr(wrapped, attr))
for attr in updated:
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
# Return the wrapper so this can be used as a decorator via partial()
return wrapper

  

2.解决方案

使用functools的update_wrapper函数可以解决该问题

如下:

def is_admin(f):
def wrapper(*args,**kwargs):
if kwargs.get(*args,**kwargs):
raise Exception("This user is not allowed to get food")
return f(*args,**kwargs)
return wrapper def foobar(username="someone"):
"""Do crazy staff"""
pass import functools
foobar = functools.update_wrapper(is_admin,foobar)
print foobar.__name__
print foobar.__doc__ 执行结果如下:
foobar
Do crazy staff

但是上述方式手工调用装饰器不太方便,我们在这里使用functools.warps的装饰器

import functools

def is_admin(f):
@functools.wraps(f)
def wrapper(*args,**kwargs):
if kwargs.get(*args,**kwargs):
raise Exception("This user is not allowed to get food")
return f(*args,**kwargs)
return wrapper @is_admin
def foobar(username="someone"):
"""Do crazy staff"""
pass
print foobar.__doc__
print foobar.__name__ 执行结果为:
Do crazy staff #####
foobar

结论:python的装饰器会导致被修饰函数的__doc__,__name__等属性丢掉,如果要保留函数的这些属性,需要在装饰器函数中添加functools.wrap装饰器;

python 装饰器的缺点以及解决方法的更多相关文章

  1. python 装饰器修改调整函数参数

    简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...

  2. Flask(2)- 装饰器的坑及解决办法、flask中的路由/实例化配置/对象配置/蓝图/特殊装饰器(中间件、重定义错误页面)

    一.装饰器的坑以及解决方法 1.使用装饰器装饰两个视图函数,代码如下 from flask import Flask, redirect, render_template, request, sess ...

  3. Python 装饰器装饰类中的方法

    title: Python 装饰器装饰类中的方法 comments: true date: 2017-04-17 20:44:31 tags: ['Python', 'Decorate'] categ ...

  4. python装饰器方法

    前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...

  5. python 装饰器 一篇就能讲清楚

    装饰器一直是我们学习python难以理解并且纠结的问题,想要弄明白装饰器,必须理解一下函数式编程概念,并且对python中函数调用语法中的特性有所了解,使用装饰器非常简单,但是写装饰器却很复杂.为了讲 ...

  6. 理解 Python 装饰器看这一篇就够了

    讲 Python 装饰器前,我想先举个例子,虽有点污,但跟装饰器这个话题很贴切. 每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,让它 ...

  7. python装饰器的作用

    常见装饰器:内置装饰器:类装饰器.函数装饰器.带参数的函数装饰器 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.它经常 ...

  8. Python装饰器基础

    一.Python装饰器引入 讲 Python 装饰器前,我想先举个例子,虽有点污,但跟装饰器这个话题很贴切. 每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个 ...

  9. python装饰器通俗易懂的解释!

    1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...

随机推荐

  1. ElasticSearch概述

    ElasticSearch 产生背景 Lucene 定义 ElasticSearch 定义  ElasticSearch vs Lucene ElasticSearch vs Solr Elastic ...

  2. bootstrap4学习—Bootstrap v4.0.0-alpha.6的快速参考

    下面为Bootstrap v4.0.0-alpha.6中的代码快速检索地址: 网址:https://hackerthemes.com/bootstrap-cheatsheet/ 在使用bootstra ...

  3. 《Linux 性能及调优指南》1.6 了解Linux性能指标

    翻译:飞哥 (http://hi.baidu.com/imlidapeng) 版权所有,尊重他人劳动成果,转载时请注明作者和原始出处及本声明. 原文名称:<Linux Performance a ...

  4. 浅析Redis 和MongoDB

    今天来聊聊什么事nosql,一听nosql也许很多人会觉得很高大上的感觉,但其实接触过了也还觉得还行,随着当今数据的疯狂爆炸性的增长,传统的RDBMS也越来越暴露出他的不足之处,所以,作为一名合格的程 ...

  5. gulp安装,淘宝镜像

    命令:express -e ./ express表示安装express -e表示使用ejs作为模板 ./表示当前目录中 (使用上面的命令之前我们应该使用npm安装express框架 sudo npm ...

  6. 将任何GitHub内的代码转为外部CDN网址

    rawgit.com 有时候在GitHub找到需要使用于网站的档案(例如:CSS.JavaScript),但没有提供CDN网址就必须自己手动下载.上传到主机上才能够使用,有点耗时又不方便,因为GitH ...

  7. 【Selenium-WebDriver自学】Selenium-IDE用户扩展(七)

    ==================================================================================================== ...

  8. 推荐算法 pd

    from django.db import connection select_sql = 'select * from model' datas = pd.read_sql(select_sql, ...

  9. SAP work process Memory allocate

    Memory allocation sequence to dialog work processes in SAP What is the memory allocation sequence to ...

  10. std::ios_base::fmtflags orig std::streamsize prec