Last active
August 29, 2015 14:23
-
-
Save tawateer/f832e5a57b6df22accc6 to your computer and use it in GitHub Desktop.
python functools 中 partial 和 wraps 的用处
This file contains hidden or 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
#!/bin/env python | |
# -*- coding: utf-8 -*- | |
""" partial 实例. | |
看上面的源代码, 可以看出 partial 接受一个函数和若干参数, 返回一个新的函数,新的函数已经包含了之前的函数和参数, | |
而新函数执行时引入的新参数会和之前的参数相加, 真正执行的函数还是之前的函数. | |
所以, partial 的作用是动态绑定参数, 第一次用 partial 生成新函数, 第二次继续绑定参数并执行. | |
""" | |
from function import partial | |
basetwo = partial(int, base=2) | |
basetwo.__doc__ = 'Convert base 2 string to an int.' | |
print basetwo('10010') |
This file contains hidden or 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
""" python 的 function.partial 是 C实现的, 这里是一个 Python 实现, 效果相同, 放在这里理解. | |
""" | |
def partial(func, *args, **keywords): | |
# print func, args, keywords | |
def newfunc(*fargs, **fkeywords): | |
newkeywords = keywords.copy() | |
newkeywords.update(fkeywords) | |
# print (args + fargs), newkeywords | |
return func(*(args + fargs), **newkeywords) | |
newfunc.func = func | |
newfunc.args = args | |
newfunc.keywords = keywords | |
#print newfunc.func, newfunc.args, newfunc.keywords | |
return newfunc |
This file contains hidden or 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
#!/bin/env python | |
""" | |
output: | |
Calling decorated function | |
Called example function | |
wrapper | |
None | |
""" | |
from functools import wraps | |
def my_decorator(f): | |
#@wraps(f) | |
def wrapper(*args, **kwds): | |
print 'Calling decorated function' | |
return f(*args, **kwds) | |
return wrapper | |
@my_decorator | |
def example(): | |
"""Docstring""" | |
print 'Called example function' | |
example() | |
print example.__name__ | |
print example.__doc__ |
This file contains hidden or 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
#!/bin/env python | |
""" | |
output: | |
Calling decorated function | |
Called example function | |
example | |
Docstring | |
""" | |
from functools import wraps | |
def my_decorator(f): | |
@wraps(f) | |
def wrapper(*args, **kwds): | |
print 'Calling decorated function' | |
return f(*args, **kwds) | |
return wrapper | |
@my_decorator | |
def example(): | |
"""Docstring""" | |
print 'Called example function' | |
example() | |
print example.__name__ | |
print example.__doc__ |
This file contains hidden or 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
""" wraps 源代码. | |
用于理解 wraps 是如何工作的. | |
""" | |
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__') | |
WRAPPER_UPDATES = ('__dict__',) | |
def update_wrapper(wrapper, | |
wrapped, | |
assigned = WRAPPER_ASSIGNMENTS, | |
updated = WRAPPER_UPDATES): | |
"""Update a wrapper function to look like the wrapped function | |
wrapper is the function to be updated | |
wrapped is the original function | |
assigned is a tuple naming the attributes assigned directly | |
from the wrapped function to the wrapper function (defaults to | |
functools.WRAPPER_ASSIGNMENTS) | |
updated is a tuple naming the attributes of the wrapper that | |
are updated with the corresponding attribute from the wrapped | |
function (defaults to functools.WRAPPER_UPDATES) | |
""" | |
for attr in assigned: | |
setattr(wrapper, attr, getattr(wrapped, attr)) | |
for attr in updated: | |
getattr(wrapper, attr).update(getattr(wrapped, attr, {})) | |
# Return the wrapper so this can be used as a decorator via partial() | |
return wrapper | |
def wraps(wrapped, | |
assigned = WRAPPER_ASSIGNMENTS, | |
updated = WRAPPER_UPDATES): | |
"""Decorator factory to apply update_wrapper() to a wrapper function | |
Returns a decorator that invokes update_wrapper() with the decorated | |
function as the wrapper argument and the arguments to wraps() as the | |
remaining arguments. Default arguments are as for update_wrapper(). | |
This is a convenience function to simplify applying partial() to | |
update_wrapper(). | |
""" | |
return partial(update_wrapper, wrapped=wrapped, | |
assigned=assigned, updated=updated) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment