使用装饰器更新包装器时遇到错误

Mad*_*May 8 python decorator attributeerror functools

在尝试使用装饰器更新函数的包装器时,我遇到了一个相当神秘的(至少对我来说)错误消息.我有什么想法可以解决这个问题吗?

我试图让我的代码尽可能通用,所以它也适用于其他情况.

def decorator(d):
    """Make function d a decorator: d wraps a function fn."""

    def _d(fn):
        return functools.update_wrapper(d(fn), fn)
    functools.update_wrapper(_d, d)
    return _d


@decorator
def f(fn):
    """Converts the string fn to a function and returns it.
    Because of the @decorator decorator, _f.__name__ should
    be identical to f.__name__"""

    f.__name__ = fn
    def _f(fn):
        return eval(fn)
    return _f

g = f('x**2')
print g.__name__
Run Code Online (Sandbox Code Playgroud)

期望的输出:

>>>x**2
Run Code Online (Sandbox Code Playgroud)

实际产量:

Traceback (most recent call last):
  File "C:\python\swampy-2.0\testcode.py", line 18, in <module>
    g = f('x**2')
  File "C:\python\swampy-2.0\testcode.py", line 6, in _d
    return functools.update_wrapper(d(fn), fn)
  File "C:\Python27\lib\functools.py", line 33, in update_wrapper
    setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'str' object has no attribute '__module__'
Run Code Online (Sandbox Code Playgroud)

std*_*err 6

装饰器将函数作为参数并返回另一个"装饰"函数.您正在传递一个字符串并尝试返回一个真正属于函数工厂的函数. functools.wrapsfunctools.update_wrapper期望的功能.函数对象具有__module__属性,而实例str没有__module__属性.

你想从字符串"x**2"生成一个函数吗?

你的实施decorator是不必要的.只需使用functools.wraps:

def f(fn):
    """Converts the string fn to a function and returns it."""
    @functools.wraps(fn)
    def _f(fn):
        return eval(fn)
    return _f
Run Code Online (Sandbox Code Playgroud)

但是,在这种情况下,您不需要装饰器,而是功能工厂.

def factory(exp):
    def f(**kwargs):
        return eval(exp, globals(), kwargs)
    f.__name__ = exp
    return f 
Run Code Online (Sandbox Code Playgroud)

现在您可以像这样使用:

>>> x_squared = factory("x**2")
>>> x_squared(x=7)
49
Run Code Online (Sandbox Code Playgroud)

警告:外科医生已经确定这eval对您的健康有害