2009-09-10 3 views
3

Как мне красиво написать декоратор?Декораторы Nice Python

В частности, вопросы включают: совместимость с другими декораторов, с сохранением подписей и т.д.

Я хотел бы избежать зависимости от модуля декоратора, если это возможно, но если имеются достаточные преимущества, то я хотел бы рассмотреть его.

Связанные

  • Preserving signatures of decorated functions - гораздо более конкретный вопрос. Ответ здесь заключается в использовании стороннего модуля декоратора, аннотирующего декоратор с помощью @ decorator.decorator

ответ

5

Написание хорошего декоратора ничем не отличается от написания хорошей функции. Это означает, в идеале, использование docstrings и обеспечение того, чтобы декоратор был включен в структуру тестирования.

Вы должны обязательно использовать библиотеку decorator или, что лучше, functools.wraps() декоратором в стандартной библиотеке (начиная с версии 2.5).

Помимо этого, ваши декораторы лучше всего сфокусированы и хорошо разработаны. Не используйте *args или **kw, если ваш декоратор ожидает конкретных аргументов. И делать заливку в какие аргументы вы ожидаете, поэтому вместо того, чтобы:

def keep_none(func): 
    def _exec(*args, **kw): 
     return None if args[0] is None else func(*args, **kw) 

    return _exec 

... использование ...

def keep_none(func): 
    """Wraps a function which expects a value as the first argument, and 
    ensures the function won't get called with *None*. If it is, this 
    will return *None*. 

    >>> def f(x): 
    ...  return x + 5 
    >>> f(1) 
    6 
    >>> f(None) is None 
    Traceback (most recent call last): 
     ... 
    TypeError: unsupported operand type(s) for +: 'NoneType' and 'int' 
    >>> f = keep_none(f) 
    >>> f(1) 
    6 
    >>> f(None) is None 
    True""" 

    @wraps(func) 
    def _exec(value, *args, **kw): 
     return None if value is None else func(value, *args, **kw) 

    return _exec 
6

Используйте functools для сохранения имени и документа. Подпись не будет сохранена.

Непосредственно из doc.

>>> from functools import wraps 
>>> def my_decorator(f): 
...  @wraps(f) 
...  def wrapper(*args, **kwds): 
...   print 'Calling decorated function' 
...   return f(*args, **kwds) 
...  return wrapper 
... 
>>> @my_decorator 
... def example(): 
...  """Docstring""" 
...  print 'Called example function' 
... 
>>> example() 
Calling decorated function 
Called example function 
>>> example.__name__ 
'example' 
>>> example.__doc__ 
'Docstring' 
+0

Его хорошо ettiquete сделать вики-ответы на свои вопросы. – voyager

+0

, что имеет смысл – Casebash

Смежные вопросы