2012-11-09 101 views
2

所以我一直坚持这个一段时间,图我会要求一些建议。我试图创建一个修饰器,可以修改函数docstring,允许可选参数或无,并且是签名保留。另外,这些都可以完成。甚至获得三个中的两个。维护签名的Python装饰器,允许修改文档字符串,并允许可选参数

下面的示例似乎修改了文档字符串,并允许可选参数或无。但是,这种方法不保留签名。

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 

我看了一下装饰模块,做维护签名,但我似乎无法修改的文档字符串。

所有的帮助感激

回答

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) 

签名被保留,该文档被修改,可选参数是允许的。输出是:

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} 
+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