Skip to content

Instantly share code, notes, and snippets.

@naiquevin
Last active December 25, 2015 05:18
Show Gist options
  • Save naiquevin/6923040 to your computer and use it in GitHub Desktop.
Save naiquevin/6923040 to your computer and use it in GitHub Desktop.
wrapping a partial
from functools import wraps, partial
def mul(a, b):
return a * b
double = partial(mul, 2)
## And now try this,
print(wraps(double)(lambda a: str(double(a)))(2))
## In Python 2.73, it fails with,
##
## AttributeError: 'functools.partial' object has no attribute
## '__module__'
## Agreed that it's highly unlikely to use wraps and partial like
## this. But it also means that if there is a decorator that uses
## @wraps, it cannot be passed a partially applied function. For eg,
## rewriting the above code as,
def as_str(f):
@wraps(f)
def dec(a):
return str(f(a))
return dec
double_as_str = as_str(double)
print(double_as_str(2))
## will again fail with AttributeError since it's effectively the
## same code
## Turns out, the reason is that partial functions don't have the
## `__module__` and `__name__` attributes.
## While this behaviour is fixed in Python 3 (tried on 3.2.3) by
## ignoring the missing attrs, not sure why it isn't fixed in 2.7 as
## well. (Not sure if the function semantics have changed
## significantly between 2 and 3 in order to keep it unfixed in 2)
##
## There is also a bug report here - http://bugs.python.org/issue3445.
## This can be worked around in Python 2 by specifying the
## `assigned` arg to `wraps` but it would require defining a special
## decorator.
print(wraps(double, assigned=('__doc__',))(lambda a: str(double(a)))(2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment