Подтвердить что ты не робот

Как документировать тип утки?

У меня есть документация наворотов на меня, так как в любое время, когда я сталкиваюсь с сложным утиным типом, мне нужно как-то сказать "этот тип утки", но вместо этого попасть в бесконечный цикл "ваша функция требует этого из этого ввода, но не документирует его", а затем документирует его. Это приводит к раздутой, повторяющейся документации, например:

def Foo(arg):
    """
    Args:
      arg: An object that supports X functionality, and Y functionality,
        and can be passed to Z other functionality.
    """
    # Insert code here.

def Bar(arg):
    """
    Args:
      arg: An object that supports X functionality, and Y functionality,
        and can be passed to Z other functionality.
    """
    # Insert code here.

И так далее и т.д. для Baz, Qux и других функций. Мне нужен более короткий способ написания "arg - это (тип объекта)".

Для некоторых типов уток это так же просто, как "диктоподобный объект": мы знаем, чего мы ожидаем от дикта, и поэтому мы знаем, что пройти. A dict или что-то, что может имитировать.

Я чувствую, что С++ имеет ту же проблему с шаблонами. Haskell получил бы это, но можно использовать определение класса типа для его документирования. (Примечание: классы Haskell!= Классы в Java/С++/Python/и т.д.) (Примечание: я действительно не программирую в Haskell, так что простите меня, если это дрянной пример.)

Должен ли я идти традиционным маршрутом OO и просто писать базовый класс и говорить "что-нибудь вроде этого базового класса" в документах? Код не будет принудительно выводить из базового класса (поскольку нет требования к тому, чтобы объект был получен из него), а базовый класс не добавляет значения, кроме как для документирования свойств интерфейса, по существу.

С другой стороны, я программирую Python, и я пытаюсь программировать в пределах идиом языка. (Как обычно, это больно.) Базовые классы хороши для наследования функциональности, но когда ваш базовый класс полностью абстрактен, он, похоже, не добавляет значения в язык с утиным языком.


РЕДАКТИРОВАТЬ. К ответам: я знаю, что такое утиная печать (это должно быть очевидно из сообщения). Где я документирую это вопрос, особенно. если класс не существует для прикрепления документации к.

4b9b3361

Ответ 1

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

Нигде в документах ни один API не указывает, что он принимает объект StringIO. Вместо этого мы в большинстве случаев ожидаем файл-подобный объект.

Кроме того, по большей части стандартная библиотека пытается избежать присвоения имен определенным методам типа утки. Это оставляет реализацию открытой для изменения. random.sample API, например, мог быть определен в терминах итераций или в терминах последовательностей.

Если вы хотите быть более конкретным, вы можете использовать абстрактные базовые классы. Некоторые из них уже включены в модуль коллекций (например, Iterable, Hashable и Sized) или номер модуля (Rational, Integral и т.д.). После того, как вы напишете, не сложно моделировать. Затем в документации просто упоминается, какие ABC необходимы (т.е. x является Sized Iterable, а y - Integral).

Ответ 2

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

Что требуется при использовании утиного ввода, не означает, что программа знает, какой тип вы используете, но это делают другие программисты. Поэтому, если у вас есть целая семья классов/функций/и т.д., Которые работают с объектами определенного типа, и этот тип не может быть описан в нескольких словах, просто добавьте раздел в комментарии или документную строку (или даже внешний .txt файл), описывающий ваш тип и называющий его. Тогда вы можете просто ссылаться на это имя везде.

Ответ 3

Более строго типизированные языки, такие как Java, имеют понятие "интерфейсы": коллекции методов, которые должен предоставлять любой класс, реализующий интерфейс.

Я предполагаю, что вы могли бы одолжить концепцию, не обязательно беря с собой багаж строгого набора: просто определите и запишите абстрактный класс Foo, а затем скажите, что ваш метод ожидает "a Foo или Foo объект". Вам даже не нужно, чтобы какой-либо другой класс действительно наследовал от Foo, если вы этого не хотите; люди, читающие документацию, по-прежнему будут знать, куда идти, чтобы узнать, что ожидается от объекта Foo.