<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Python 修饰器与 functools
Python 的修饰器是一种语法糖（Syntactic Sugar），也就是说：
python
@decorator
@wrap
def func()
Step1:  修饰类
除了修饰函数之外，Python 3.0 之后增加了对新定义类的修饰（PEP 3129），但是对于类别属性的修改可以通过 Metaclasses 或继承来实现，而新增加的类别修饰器更多是出于 Jython 以及 IronPython 的考虑，但其语法还是很一致的：
Step3:  类作为修饰器
上面两个例子都是以函数作为修饰器，因为函数才可以被调用（callable） decorator(wrap(func))。除了函数之外，我们也可以定义可被调用的类，只要添加 __call__ 方法即可：
Step4:  传递参数
在实际使用过程中，我们可能需要向修饰器传递参数，也有可能需要向被修饰的函数（或类）传递参数。按照语法约定，只要修饰器 @decorator 中的 decorator 是可调用即可，decorator(123) 如果返回一个新的可调用函数，那么也是合理的，上面的 @HTML('html') 即是一例，下面再以 flask 的路由修饰器为例说明如何传递参数给修饰器：
Step5:  向被修饰的函数传递参数，要看我们的修饰器是如何作用的，如果像上面这个例子一样未执行被修饰函数只是将其原模原样地返回，则不需要任何处理（这就把函数当做普通的值一样看待即可）：
Step6:  如果需要在修饰器内执行，则需要稍微变动一下：
Step8:  functools
由于修饰器将函数（或类）进行包装之后重新返回：func = decorator(func)，那么有可能改变原本函数（或类）的一些信息，以上面的 HTML 修饰器为例：
Step12:  因为 body = HTML("body")(body) ，而 HTML("body").__call__() 返回的是一个 lambda 函数，因此 body 已经被替换成了 lambda，虽然都是可执行的函数，但原来定义的 body 中的一些属性，例如 __doc__/__name__/__module__ 都被替换了（在本例中__module__没变因为都在同一个文件中）。为了解决这一问题 Python 提供了 functools 标准库，其中包括了 update_wrapper 和 wraps 两个方法（源码）。其中 update_wrapper 就是用来将原来函数的信息赋值给修饰器中返回的函数：
Step14:  有趣的是 update_wrapper 的用法本身就很像是修饰器，因此 functools.wraps 就利用 functools.partial（还记得函数式编程中的偏应用吧！）将其变成一个修饰器：
<ASSISTANT_TASK:>
Python Code:
def log(func):
    def wraper():
        print("INFO: Starting {}".format(func.__name__))
        func()
        print("INFO: Finishing {}".format(func.__name__))
    return wraper
@log
def run():
    print("Running run...")
run()
Explanation: Python 修饰器与 functools
Python 的修饰器是一种语法糖（Syntactic Sugar），也就是说：
python
@decorator
@wrap
def func():
    pass
是下面语法的一种简写：
python
def func():
    pass
func = decorator(wrap(func))
关于修饰器的两个主要问题：
修饰器用来修饰谁
谁可以作为修饰器
修饰函数
修饰器最常见的用法是修饰新定义的函数，在 0x0d 上下文管理器中提到上下文管理器主要是为了更优雅地完成善后工作，而修饰器通常用于扩展函数的行为或属性：
End of explanation
from time import sleep, time
def timer(Cls):
    def wraper():
        s = time()
        obj = Cls()
        e = time()
        print("Cost {:.3f}s to init.".format(e - s))
        return obj
    return wraper
@timer
class Obj:
    def __init__(self):
        print("Hello")
        sleep(3)
        print("Obj")
o = Obj()
Explanation: 修饰类
除了修饰函数之外，Python 3.0 之后增加了对新定义类的修饰（PEP 3129），但是对于类别属性的修改可以通过 Metaclasses 或继承来实现，而新增加的类别修饰器更多是出于 Jython 以及 IronPython 的考虑，但其语法还是很一致的：
End of explanation
class HTML(object):
    
        Baking HTML Tags!
    
    def __init__(self, tag="p"):
        print("LOG: Baking Tag <{}>!".format(tag))
        self.tag = tag
    def __call__(self, func):
        return lambda: "<{0}>{1}</{0}>".format(self.tag, func(), self.tag)
@HTML("html")
@HTML("body")
@HTML("div")
def body():
    return "Hello"
print(body())
Explanation: 类作为修饰器
上面两个例子都是以函数作为修饰器，因为函数才可以被调用（callable） decorator(wrap(func))。除了函数之外，我们也可以定义可被调用的类，只要添加 __call__ 方法即可：
End of explanation
RULES = {}
def route(rule):
    def decorator(hand):
        RULES.update({rule: hand})
        return hand
    return decorator
@route("/")
def index():
    print("Hello world!")
def home():
    print("Welcome Home!")
home = route("/home")(home)
index()
home()
print(RULES)
Explanation: 传递参数
在实际使用过程中，我们可能需要向修饰器传递参数，也有可能需要向被修饰的函数（或类）传递参数。按照语法约定，只要修饰器 @decorator 中的 decorator 是可调用即可，decorator(123) 如果返回一个新的可调用函数，那么也是合理的，上面的 @HTML('html') 即是一例，下面再以 flask 的路由修饰器为例说明如何传递参数给修饰器：
End of explanation
@route("/login")
def login(user = "user", pwd = "pwd"):
    print("DB.findOne({{{}, {}}})".format(user, pwd))
login("hail", "python")
Explanation: 向被修饰的函数传递参数，要看我们的修饰器是如何作用的，如果像上面这个例子一样未执行被修饰函数只是将其原模原样地返回，则不需要任何处理（这就把函数当做普通的值一样看待即可）：
End of explanation
def log(f):
    def wraper(*args, **kargs):
        print("INFO: Start Logging")
        f(*args, **kargs)
        print("INFO: Finish Logging")
    return wraper
@log
def run(hello = "world"):
    print("Hello {}".format(hello))
run("Python")
Explanation: 如果需要在修饰器内执行，则需要稍微变动一下：
End of explanation
@HTML("body")
def body():
    
        return body content
    
    return "Hello, body!"
print(body.__name__)
print(body.__doc__)
Explanation: functools
由于修饰器将函数（或类）进行包装之后重新返回：func = decorator(func)，那么有可能改变原本函数（或类）的一些信息，以上面的 HTML 修饰器为例：
End of explanation
from functools import update_wrapper
functools.update_wrapper(wrapper, wrapped[, assigned][, updated])
class HTML(object):
    
        Baking HTML Tags!
    
    def __init__(self, tag="p"):
        print("LOG: Baking Tag <{}>!".format(tag))
        self.tag = tag
    def __call__(self, func):
        wraper = lambda: "<{0}>{1}</{0}>".format(self.tag, func(), self.tag)
        update_wrapper(wraper, func)
        return wraper
@HTML("body")
def body():
    
        return body content!
    
    return "Hello, body!"
print(body.__name__)
print(body.__doc__)
Explanation: 因为 body = HTML("body")(body) ，而 HTML("body").__call__() 返回的是一个 lambda 函数，因此 body 已经被替换成了 lambda，虽然都是可执行的函数，但原来定义的 body 中的一些属性，例如 __doc__/__name__/__module__ 都被替换了（在本例中__module__没变因为都在同一个文件中）。为了解决这一问题 Python 提供了 functools 标准库，其中包括了 update_wrapper 和 wraps 两个方法（源码）。其中 update_wrapper 就是用来将原来函数的信息赋值给修饰器中返回的函数：
End of explanation
from functools import update_wrapper, partial
def my_wraps(wrapped):
    return partial(update_wrapper, wrapped=wrapped)
def log(func):
    @my_wraps(func)
    def wraper():
        print("INFO: Starting {}".format(func.__name__))
        func()
        print("INFO: Finishing {}".format(func.__name__))
    return wraper
@log
def run():
    
    Docs' of run
    
    print("Running run...")
print(run.__name__)
print(run.__doc__)
Explanation: 有趣的是 update_wrapper 的用法本身就很像是修饰器，因此 functools.wraps 就利用 functools.partial（还记得函数式编程中的偏应用吧！）将其变成一个修饰器：
End of explanation
<END_TASK>