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__'
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With