
一名二三线城市物联网行业程序员,卡在黄风怪吃灰中,非著名脑洞开发者。感谢您抽出时间来阅读我的文章,开心地多啃了三根草。
卡卡正在给团队肝一份“有手就行”的公共代码,为了让队友们秒懂且能无脑调用,我直接献祭了十几年修炼的语文功底,给每个函数都写起了小作文。
代码的样子就像下面这样:
defhello():''' 这里是一个hello函数 :return: int '''return0如此一来,虽然为此头发掉了不少,但胜在“对队友像春天般温暖”,直接在小伙伴心里把自己写成了“史诗级文档侠”,形象瞬间两米八。

为了归档,卡卡利用每个函数的 __name__ 和 __doc__ 输出成一个html,这就变成了非常直观方便的函数手册,堪称完美。

但是在开发过程中发现需要一个通用方法去控制每个函数的输出,这难不倒卡卡,直接加上一个 装饰器,手拿把掐。
defhandler(f):definner(*args, **kwargs):return f(*args, **kwargs)return inner@handlerdefhello():''' 这里是一个hello函数 :return: int '''return0不过,此时发生了意外,再来看那html手册,竟然出现了纰漏:

函数名称变为了装饰器中的 inner,函数描述竟然成了 None,这不是让我掉了那么多头发写的描述都白费了吗?
一个函数在被使用装饰器的情况下,它的元数据将会丢失,即 __name__ 、__doc__ 等等,取而代之的是会被装饰器中的闭包函数替代,因此如果我们如下修改,便会输出闭包函数的内容:
defhandler(f):def inner(*args, **kwargs):''' 这里是闭包 '''return f(*args, **kwargs)return inner@handlerdef hello():''' 这里是一个hello函数 :return: int '''return0print(hello.__name__) # innerprint(hello.__doc__) # 这里是闭包可想而知,这不是卡卡所希望看到的,我们需要以前的函数元数据来输出成文档手册。
有没有办法解决这个问题?当然有,python团队早就提供了相应的方法 @wraps。
没错,这个 wraps 也是一个装饰器,它的用法如下:
from functools import wrapsdef handler(f): @wraps(f)def inner(*args, **kwargs):''' 这里是闭包 '''return f(*args, **kwargs)return inner@handlerdef hello():''' 这里是一个hello函数 :return: int '''return 0print(hello.__name__) # helloprint(hello.__doc__) # 这里是一个hello函数...此时输出正是函数原来的元数据内容,完美解决这次危机。
在python内部有非常多实用的内置方法,可以帮助我们解决许多奇奇怪怪的问题。
即使目前你遇到的问题没法解决,相信在未来,python团队也会慢慢升级迭代,去适配解决这些普世问题。
往期回顾:
用python解锁知识付费:我们做了一个「不翻车」的群聊系统