为什么装饰 class 会丢失其文档字符串?

Why does a decorated class looses its docstrings?

我目前正在实现一个 API,我需要在其上修饰 class Wrapper,但我希望它保留其文档字符串以供 API 用户。看看下面的最小工作示例:

class ClassDecorator:
    """ClassDecorator docstring
    """
    def __init__(self, enableCache=True):
        self.enableCache = enableCache

    def __call__(self, wrapper):
        def numericalmathfunction(*args, **kwargs):
            func = wrapper(*args, **kwargs)
            return func
        return numericalmathfunction

@ClassDecorator(enableCache=True)
class Wrapper(object):
    """Wrapper docstring
    Instructions on how to use the Wrapper
    """
    def __init__(self, p):
        self.p = p

model = Wrapper(4)
print model.__doc__
print Wrapper.__doc__

这个returns

Wrapper docstring
None

Wrapper 的实例确实保留了文档字符串,这很好,但 Wrapper 本身没有。如果用户想通过 help(Wrapper) 学习如何使用 Wrapper,他将得不到他想要的。

我知道我可以将文档字符串复制粘贴到 numericalmathfunction,但是装饰器将用于多个具有不同文档字符串的 classes。

关于如何使 numericalmathfunction 系统地继承包装的 class 的文档字符串的任何想法?

使用functools.wraps()更新装饰器的属性:

from functools import wraps

class ClassDecorator:
    """ClassDecorator docstring
    """
    def __init__(self, enableCache=True):
        self.enableCache = enableCache

    def __call__(self, wrapper):
        @wraps(wrapper)                              # <-----------
        def numericalmathfunction(*args, **kwargs):
            func = wrapper(*args, **kwargs)
            return func
        return numericalmathfunction

@ClassDecorator(enableCache=True)
class Wrapper(object):
    """Wrapper docstring
    Instructions on how to use the Wrapper
    """
    def __init__(self, p):
        self.p = p

查看 functools.wrap 的更多标准库文档。