2015-06-08 3 views
3

Я в настоящее время реализую API, для которого мне нужно украсить класс Wrapper, но я хочу, чтобы он сохранил свою docstring, чтобы сделать его доступным для пользователя 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__ 

Это возвращает

Wrapper docstring 
None 

Случаев Wrapper имейте в строку документации, которая хорошо, но Wrapper сам не делает. Если пользователь хочет узнать, как использовать Wrapper, используя help(Wrapper), он не получит то, что хочет.

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

Любые идеи о том, как сделать numericalmathfunction, систематически наследуют docstrings обернутого класса?

+2

Поскольку обертка теперь технически относится к классу, который вызывается первым. Посмотрите на '@ wraps' [здесь] (https://docs.python.org/2/library/functools.html#functools.wraps) – Jkdc

ответ

4

Использование 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.

+0

Отлично, он работает. Есть ли аналогичное решение, чтобы украшенная функция наследовала атрибуты класса? Я уже нашел решение этого (см. [Здесь] (http://stackoverflow.com/questions/30711730/decorated-class-looses-acces-to-its-attributes)), но мне было интересно, есть ли что-то подобный '@ wraps'. –

+0

Не то, чтобы я знал. Вы можете легко написать декоратор обертки на основе ответа в этой ссылке и использовать его повсюду. Это должно работать так же, как '@ wraps'. – ronakg

+0

Хорошо, я попробую позже, чтобы сделать код более элегантным. На данный момент у меня уже есть рабочее решение. Спасибо –

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