Будет ли необязательная статическая типизация пользой для разработки Python API или недостатком? (включен пример декоратора проверки типов)

Я долгое время разрабатываю Python, и мне очень нравится динамическая природа языка, но мне интересно, выиграет ли Python от необязательной статической типизации. Была бы полезна возможность применять статическую типизацию к API библиотеки и каковы были бы недостатки этого?

Я быстро набросал декоратор, реализующий статическую проверку типов во время выполнения в pastebin, и он работает следующим образом:

# A TypeError will be thrown if the argument "string" is not a "str" and if 
# the returned value is not an "int"
@typed(int, string = str)
def getStringLength(string):
    return len(string)

Будет ли практично использовать такой декоратор в API-функциях библиотеки? С моей точки зрения, проверка типов не требуется во внутренней работе предметно-ориентированного модуля библиотеки, но в точках соединения между библиотекой и ее клиентом может быть полезна простая версия проектирования по контракту с применением проверки типов. Особенно как тип обязательной документации, которая четко указывает клиенту библиотеки, что он ожидает и возвращает.

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

# some_library_module.py

@typed(int, name = string)
def addObjectToQueue(name):
    return random.randint() # Some object id

def processTheQueueAndDoAdvancedStuff(arg_of_library_specific_type)
    # Function body here

@typed(bool, object_id = int)
def isObjectProcessed(object_id):
    return True

Каковы недостатки использования этого метода? Каковы будут недостатки моей наивной реализации на pastebin?

Мне не нужны ответы, обсуждающие преобразование Python в язык со статической типизацией, но мне нужны мысли о плюсах и минусах дизайна API. (пожалуйста, переместите это наprogramrs.stackexchange.com, если вы считаете, что это не вопрос)


person Anton B    schedule 28.01.2012    source источник
comment
What would the disadvantages of using this technique be? Потеря утиного набора текста.   -  person Lie Ryan    schedule 29.01.2012


Ответы (1)


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

Основные преимущества статической типизации я вижу следующим образом:

  1. Повышенная вероятность того, что ваш код будет правильным после того, как компилятор его примет; если я знаю, что пропустил свои значения через все операции, которые я вызывал таким образом, что тип результата одной всегда совпадает с типом ввода другой, а конечный тип результата — тот, который я хотел, это увеличивает вероятность того, что я выбрали правильные операции. Этот момент имеет очень спорное значение, поскольку он действительно имеет значение только в том случае, если вы не очень много тестируете, что было бы плохо. Но это правда, что при программировании на Haskell, когда я сажусь и говорю: "Вот, готово!" Я на самом деле делаю много времени, тогда как это почти никогда не верно для моего кода Python.
  2. Компилятор автоматически указывает на большинство мест, которые необходимо изменить, когда я делаю несовместимое изменение в структуре данных или интерфейсе (в большинстве случаев). Опять же, тесты по-прежнему необходимы, чтобы убедиться, что вы действительно уловили все последствия, но в большинстве случаев, по моему опыту, на самом деле достаточно ворчания компилятора, что значительно упрощает такой рефакторинг; вы можете сразу перейти от реализации ядра рефакторинга к тестированию того, что программа все еще работает нормально, потому что фактическая работа по внесению всех текущих изменений почти механическая.
  3. Эффективная реализация. Компилятор использует все свои знания о типах для оптимизации.

Предлагаемая вами система на самом деле не обеспечивает ни одного из этих преимуществ.

  1. Написав программу, использующую вашу библиотеку, я до сих пор не знаю, содержит ли она какое-либо некорректное использование ваших функций, пока не проведу всестороннее тестирование с полным охватом кода, чтобы увидеть, содержит ли какой-либо путь выполнения неверный вызов.
  2. Когда я что-то реорганизую, мне нужно пройти много-много циклов «запустить полный набор тестов, найти исключение, найти, откуда оно взялось, исправить код», чтобы получить хоть что-то вроде обнаружения проблем компилятором статической типизации.
  3. Python по-прежнему будет вести себя так, как будто эти переменные могут быть чем угодно в любое время.

И чтобы получить даже это, вы пожертвовали гибкостью утиного набора Python; недостаточно того, что я предоставляю достаточно «спископодобный» объект, я должен фактически предоставить список.

Для меня такая статическая типизация — худшее из обоих миров. Основной аргумент динамической типизации: «Вы все равно должны тестировать свой код, так что вы также можете использовать эти тесты для обнаружения ошибок типов и освободить себя от необходимости работать с системой типов, когда она вам не помогает». Это может быть или не быть хорошим аргументом в отношении действительно хорошей статической системы типов, но это абсолютно убедительный аргумент в отношении слабой частично статической системы типов, которая обнаруживает ошибки типов только во время выполнения. Я не думаю, что более приятные сообщения об ошибках (это все, за что вы действительно покупаете большую часть времени; ошибка типа, не обнаруженная в интерфейсе, почти наверняка вызовет исключение глубже в стеке вызовов) стоит потери гибкости.

person Ben    schedule 28.01.2012