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. JavaBean转xml

    JavaBean转xml的工具就是:XStream XStream的作用: XStream可以把JavaBean对象转换成XML!通常服务器向客户端响应的数据都是来自数据库的一组对象,当我们不能直接把 ...

  2. 在django中,执行原始sql语句

    extra()方法 结果集修改器,一种提供额外查询参数的机制 使用extra: 1:Book.objects.filter(publisher__name='广东人员出版社').extra(where ...

  3. Css实战第二天小结

    清除浮动的四种方式: 1.1    给父盒子设置一个高度: 1.2    Clear:both; 1.3    Overflow:hidden; 1.4    使用伪元素 .clearfix:befo ...

  4. How Computers Boot Up.计算机的引导过程

    原文标题:How Computers Boot Up 原文地址:http://duartes.org/gustavo/blog/ [注:本人水平有限,只好挑一些国外高手的精彩文章翻译一下.一来自己复习 ...

  5. 使用Solrj 获取语句分词结果的代码

    import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.log4 ...

  6. Java分布式锁的三种实现方案(redis)

    方案一:数据库乐观锁 乐观锁通常实现基于数据版本(version)的记录机制实现的,比如有一张红包表(t_bonus),有一个字段(left_count)记录礼物的剩余个数,用户每领取一个奖品,对应的 ...

  7. linux:Apache服务器相关

    安装apache服务器 (推荐方法) 安装前清确保已安装gcc.g++ 1)安装依赖包apr-1.6.5.tar.gz,下载地址:http://apr.apache.org/download.cgi ...

  8. redis的哨兵集群,redis-cluster

    #主从同步redis主从优先1.保证数据安全,主从机器两份数据一主多从2.读写分离,缓解主库压力主redis,可读可写slave身份,只读   缺点1.手动主从切换假如主库挂了,得手动切换master ...

  9. websocket如何设置?

    根据之前写的步骤到当前的websocket设置 一.websocket设置: 1)在线程租下右键单击选择Sampler如图: 2)进行它的设置 2.保存 3.添加查看结果数和聚合报告(此处不详细说明, ...

  10. spring的IOC 的底层实现原理

    IOC:Inversion of Control  控制反转. 指的是 对象的创建权反转(交给)给 Spring. 作用是实现了程序的解耦合.