python 动态添加装饰器_python – 动态创建方法和装饰器,得到错误...

我也偶然发现了这一点,我真的很惊讶,对我来说问题是部分对象缺少某些属性,特别是__module__和__name__

默认使用functools.WRAPPER_ASSIGNMENTS来更新属性,默认为python 2.7.6中的”__module __,’_ _ _ _ _ _ _ _’,’_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ….

仅更新当前属性…

import functools

import itertools

def wraps_safely(obj, attr_names=functools.WRAPPER_ASSIGNMENTS):

return wraps(obj, assigned=itertools.ifilter(functools.partial(hasattr, obj), attr_names))

>>> def foo():

... """ Ubiquitous foo function ...."""

...

>>> functools.wraps(partial(foo))(foo)()

Traceback (most recent call last):

File "", line 1, in

File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/functools.py", line 33, in update_wrapper

setattr(wrapper, attr, getattr(wrapped, attr))

AttributeError: 'functools.partial' object has no attribute '__module__'

>>> wraps_safely(partial(foo))(foo)()

>>>

在这里,我们只是过滤掉所有不存在的属性.

另一种方法是仅严格处理部分对象,您可以使用singledispatch折叠包装并创建包含的部分对象,其属性将从最深的func属性中获取.

一些事情:

import functools

def wraps_partial(wrapper, *args, **kwargs):

""" Creates a callable object whose attributes will be set from the partials nested func attribute ..."""

wrapper = wrapper.func

while isinstance(wrapper, functools.partial):

wrapper = wrapper.func

return functools.wraps(wrapper, *args, **kwargs)

def foo():

""" Foo function.

:return: None """

pass

>>> wraps_partial(partial(partial(foo)))(lambda : None).__doc__

' Foo Function, returns None '

>>> wraps_partial(partial(partial(foo)))(lambda : None).__name__

'foo'

>>> wraps_partial(partial(partial(foo)))(lambda : None)()

>>> pfoo = partial(partial(foo))

>>> @wraps_partial(pfoo)

... def not_foo():

... """ Not Foo function ... """

...

>>> not_foo.__doc__

' Foo Function, returns None '

>>> not_foo.__name__

'foo'

>>>

这稍微好一点,因为现在我们可以获得默认使用部分对象文档字符串之前的原始函数文档.

这可以修改为仅搜索当前部分对象是否还没有set属性,嵌套多个部分对象时应该稍快一些…

UPDATE

似乎python(CPython)3(至少3.4.3)没有这个问题,因为我不知道也不应该假设所有版本的python 3或其他实现如Jython也在这里分享这个问题是另一个未来的准备方法

from functools import wraps, partial, WRAPPER_ASSIGNMENTS

try:

wraps(partial(wraps))(wraps)

except AttributeError:

@wraps(wraps)

def wraps(obj, attr_names=WRAPPER_ASSIGNMENTS, wraps=wraps):

return wraps(obj, assigned=(name for name in attr_names if hasattr(obj, name)))

有几点需要注意:

>我们定义一个新的包装函数,只有当我们无法包装部分时,以防python2或其他版本的未来版本修复此问题.

>我们使用原始包装来复制文档和其他信息

>我们不使用ifilter,因为它已经在python3中删除了,我有时间和没有ifilter,但结果是不确定的,至少在python(CPython)2.7.6中,差异在最好的方式是最小的……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值