Last active
December 25, 2015 05:18
-
-
Save naiquevin/6923040 to your computer and use it in GitHub Desktop.
wrapping a partial
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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