Error encountered using decorator to update wrapper
attributeerror, decorator, functools, python
Solution
A decorator takes a function as an argument and returns another "decorated" function. You're passing a string and attempting to return a function which is really a function factory. `functools.wraps` and `functools.update_wrapper` expect a function. A function object would have a `__module__` attribute while instances of `str` don't have an `__module__` attribute.
Do you want to generate a function from the string "x**2"?
Your implementation of `decorator` is unnecessary. Just use `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
However, you don't want a decorator in this case but a function factory.
def factory(exp):
def f(**kwargs):
return eval(exp, globals(), kwargs)
f.__name__ = exp
return f
Now you can use this like this:
>>> x_squared = factory("x**2")
>>> x_squared(x=7)
49
Warning: The Surgeon General Has Determined that `eval` is Dangerous to Your Health
Problem
I've encountered a rather cryptic (to me at least) error message while trying to use a decorator to update a function's wrapper. Any ideas how I could remedy this? I've tried to make my code as general as possible so it will apply to other situations as well. ``` 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__ ``` Desired output: ``` >>>x**2 ``` Actual output: ``` 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__' ```