维护签名的Python Decorator允许修改docstring,并允许可选参数

时间:2012-11-09 18:44:24

标签: python decorator

所以我已经坚持了一段时间,并且我想要一些建议。我试图创建一个装饰器,可以修改函数docstring,允许可选参数或无,并且是签名保留。另外,这些都可以完成。甚至得到三个中的两个。

下面的示例似乎修改了docstring并允许可选参数或none。但是,此方法不保留签名。

from functools import wraps
def thisDecorator(*targs, **tkwargs):
    def internalFunc(func):
        func.__doc__ = "Added this... {0}".format(func.__doc__)
        @wraps(func)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapper
    if len(targs) == 1 and callable(targs[0]):
        return internalFunc(targs[0])
    else:
        return internalFunc

我已经阅读了有关保留签名的装饰器模块,但我似乎无法修改docstring。

非常感谢所有帮助

2 个答案:

答案 0 :(得分:3)

通过向内部包装器添加装饰器,这将保留功能签名。

from functools import wraps
from decorator import decorator

def thisDecorator(*targs, **tkwargs):
    def internalFunc(func):
        func.__doc__ = "Added this... {0}".format(func.__doc__)
        @wraps(func)
        def wrapper(func, *args, **kwargs):
            return func(*args, **kwargs)
        return decorator(wrapper, func)
    if len(targs) == 1 and callable(targs[0]):
        return internalFunc(targs[0])
    else:
        return internalFunc

答案 1 :(得分:0)

也许我不完全理解你的要求,但这似乎对我有用:

class myDeco:
    def __init__(self, f):
        self.f = f
        if f.__doc__:
            self.__doc__ = 'great doc: ' + f.__doc__
        else:
            self.__doc__ = 'ooohh, no doc'
    def __call__(self, *args, **kwargs):
        print "decorator args and kwargs: {0}, {1}".format(args, kwargs)
        self.f(*args, **kwargs)

@myDeco
def test1():
    """test1 doc"""
    print 'test1'

@myDeco
def test2(a, b):
    print 'test2: {0}, {1}'.format(a,b)

@myDeco
def test3(a, *args):
    print "test3: {0}, {1}".format(a, args)

@myDeco
def test4(a, *args, **kwargs):
    print "test4: {0}, {1}, {2}".format(a, args, kwargs)


print test1.__doc__
print test2.__doc__
print test3.__doc__
print test4.__doc__

test1()
test2(1,2)
test3(1,2,3)
test4(1,2,3, foo=4, bar=5)

保留签名,修改doc,允许使用可选参数。输出是:

great doc: test1 doc
ooohh, no doc
ooohh, no doc
ooohh, no doc
decorator args and kwargs: (), {}
test1
decorator args and kwargs: (1, 2), {}
test2: 1, 2
decorator args and kwargs: (1, 2, 3), {}
test3: 1, (2, 3)
decorator args and kwargs: (1, 2, 3), {'foo': 4, 'bar': 5}
test4: 1, (2, 3), {'foo': 4, 'bar': 5}