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

标签 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__

期望的输出:

>>>x**2

实际输出:

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__'

最佳答案

装饰器将一个函数作为参数并返回另一个“装饰过的”函数。您正在传递一个字符串并试图返回一个实际上是函数工厂的函数。 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

但是,在这种情况下您不需要装饰器,而是需要函数工厂。

def factory(exp):
    def f(**kwargs):
        return eval(exp, globals(), kwargs)
    f.__name__ = exp
    return f 

现在你可以这样使用了:

>>> x_squared = factory("x**2")
>>> x_squared(x=7)
49

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

关于python - 使用装饰器更新包装器时遇到错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11960007/

相关文章:

node.js - 如何使用和应用 JavaScript 装饰器?

java - 为什么 FilterOutputStream 是一个具体的类?

python - 如果元素包含特定字符,则从列表或集合中删除元素

python - 在异常/错误的情况下如何不停止 python 中其他函数的执行

python - 带有 paramiko 的 ssh 客户端 (python)

python flask : AttributeError: 'NoneType' object has no attribute 'is_active'

python - 合并两个数组python的所有元素

Python:使用 matplotlib 绘制 x-y 图

python - 在 python tornado 的 web 请求处理程序中,是否应该设置 mysql 的全局连接?

python - 我该如何结束这个循环?