Существует ли необходимость в использовании "строгого" компилятора Python?

Существуют инструменты статического анализа для Python, но проверки времени компиляции, как правило, диаметрально противоположны философия привязки времени выполнения, которую охватывает Python. Можно поместить стандартный интерпретатор Python с помощью инструмента статического анализа, чтобы принудительно использовать некоторые ограничения use strict", но мы не видим любое широко распространенное принятие такой вещи.

Есть ли что-то о Python, которое делает "использование строгих" действий ненужным или особенно нежелательным?

В качестве альтернативы, использование "строгого" поведения не нужно в Perl, несмотря на его широкое применение?

Примечание. Под "необходимым" я подразумеваю "практически необходимый", а не строго необходимый. Очевидно, вы можете написать Perl без "строгого использования", но (из того, что я видел) большинство программистов на Perl действительно используют его.

Примечание. Для интерпретатора-интерпретатора Python не требуется "использовать строгие" -подобные ограничения - вы можете использовать псевдо-прагму, подобную "use strict" , которая будет игнорироваться обычным интерпретатором. Я не говорю о добавлении функции уровня языка.


Обновление. Объяснение того, что делает "use strict" в Perl для комментариев. (Ссылка на официальные документы находится в первом абзаце.)

Директива "use strict" имеет три различных компонента, только две из которых действительно интересны:

  • использовать строгие vars: статически проверяет использование переменной в лексической области в вашей программе. (Имейте в виду, что в Python существует только область global и область local). Многие листы Python проверяют это. Поскольку это единственный статический анализ, который они могут сделать, линтеры предполагают, что вы используете прямое лексическое охват и предупреждаете вас о вещах, которые кажутся неправильными в этом смысле, пока вы не скажете им заткнуться; то есть.

    FOO = 12
    foo += 3
    

    Если вы ничего не делаете с вашими пространствами имен, это может быть полезно для проверки опечаток.

  • Использовать строгие ссылки: Предотвращает разглашение символического пространства имен. Самый близкий аналог Python использует locals() и globals() для выполнения символической привязки и поиска идентификатора.

  • использовать строгие субтитры: нет реального аналога в Python.

+30
источник поделиться
12 ответов

"философия привязки времени выполнения, которую охватывает Python... делает ненужным использование" строгого "поведения [и] особенно нежелательным"

Довольно хорошее резюме. Спасибо.

Это по существу это. Инструменты статического анализа не помогают Python достаточно стоять.


Edit

"Я прошу нас понять, почему это нам не нужно, и, соответственно, почему программисты на Perl считают, что им это нужно".

Причина, по которой именно вы уже дали. Нам это не нужно, потому что это не помогает. Понятно, что вам не нравится этот ответ, но еще нечего сказать. Проверка времени компиляции или предварительной компиляции просто не помогает.

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

Я пишу Java почти так же, как пишу Python. Проверка статического типа Java не мешает логическим проблемам; это не способствует удовлетворению требований к исполнению; это не помогает удовлетворить случаи использования. Он даже не уменьшает объем модульных испытаний.

В то время как проверка статического типа указывает на случайное неправильное использование метода, вы обнаружите это так же быстро в Python. В Python вы найдете его в unit test, потому что он не будет работать. Примечание: я не говорю, что неправильные типы найдены с большим количеством умных модульных тестов, я говорю, что проблемы с неправильным типом обнаруживаются через необработанные исключения, когда вещь просто не будет работать достаточно далеко, чтобы проверять утверждения.

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

Посмотрите на наиболее популярные вопросы SO Python, которые связаны с языком (не проблемным доменом или библиотекой).

Есть ли разница между "foo is None" и "и" foo == None ", - == и is. Никакая статическая проверка не может помочь в этом. Кроме того, см. Есть ли разница между` == `и` is` в Python?

Что делает ** (двойная звезда) и * (звезда) для параметров? - *x дает список, **x дает словарь. Если вы этого не знаете, ваша программа сразу же умирает, когда вы пытаетесь сделать что-то неуместное для этих типов. "Что делать, если ваша программа никогда ничего не делает" неуместно ". Тогда ваша программа работает. - сказал он.

Как я могу представить "Enum" в Python? - это призыв к типу ограниченного домена. Класс со значениями уровня класса в значительной степени выполняет эту работу. "Что, если кто-то изменит назначение". Простота сборки. Переопределите __set__, чтобы создать исключение. Да, статическая проверка может заметить это. Нет, на практике не бывает, что кто-то путается с константой перечисления и переменной; и когда они это делают, его легко обнаружить во время выполнения. "Что, если логика никогда не будет выполнена". Ну, это плохой дизайн и плохое модульное тестирование. Выброс ошибки компилятора и неправильная логика, которая никогда не тестировалась, не лучше, чем то, что происходит на динамическом языке, когда он никогда не тестировался.

Выражения генератора и понимание списков - статическая проверка не помогает решить этот вопрос.

Почему 1 +++ 2 = 3? - статическая проверка не заметила бы этого. 1 +++ 2 в C совершенно закончен, несмотря на все проверки компилятора. Это не то же самое в Python, как и на C, но так же законно. И так же запутанно.

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

+12
источник

Ну, я не очень программист на питоне, но я бы сказал, что ответ "ДА".

Любой динамический язык, который позволяет вам создавать переменную с любым именем в любое время, может использовать "строгую" прагму.

Строгие вары (одна из опций для строгих в Perl, "use strict" включает все их сразу), в Perl требуется, чтобы все переменные были объявлены до их использования. Это означает, что этот код:

my $strict_is_good = 'foo';
$strict_iS_good .= 'COMPILE TIME FATAL ERROR';

Генерирует фатальную ошибку во время компиляции.

Я не знаю, как заставить Python отклонять этот код во время компиляции:

strict_is_good = 'foo';
strict_iS_good += 'RUN TIME FATAL ERROR';

Вы получите исключение во время выполнения, которое strict_iS_good равно undefined. Но только при выполнении кода. Если ваш набор тестов не имеет 100% -ного охвата, вы можете легко отправить эту ошибку.

Каждый раз, когда я работаю на языке, который не имеет такого поведения (например, PHP), я нервничаю. Я не идеальная машинистка. Простая, но трудно различимая опечатка может привести к тому, что ваш код завершится неудачно, что может быть трудно отследить.

Итак, чтобы повторить, ДА Python может использовать "строгую" прагму, чтобы включить проверку времени компиляции для вещей, которые можно проверить во время компиляции. Я не могу придумать какие-либо другие проверки, чтобы добавить, но лучший программист на Python, вероятно, мог бы подумать о некоторых.

Примечание Я сосредотачиваюсь на прагматическом эффекте stict vars в Perl и замалчиваю некоторые детали. Если вы действительно хотите узнать все подробности, см. perldoc для строгого.

Обновление: ответы на некоторые комментарии

Джейсон Бейкер: Статические шашки, такие как pylint, полезны. Но они представляют собой дополнительный шаг, который может быть и часто пропускается. Построение некоторых основных проверок в компиляторе гарантирует, что эти проверки выполняются последовательно. Если эти проверки контролируются прагмой, даже возражение, связанное с стоимостью проверок, становится спорным.

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

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

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

Я не достаточно хорошо знаком с pylint и pychecker, чтобы сказать, какие классы ошибок они поймают. Как я уже сказал, я очень неопытен с питоном.

Эти программы статического анализа полезны. Тем не менее, я считаю, что, если они не дублируют возможности компилятора, компилятор всегда будет в состоянии "знать" больше о программе, чем любая статичная проверка. Кажется расточительным не использовать это для уменьшения ошибок там, где это возможно.

Обновление 2:

cdleary. Теоретически, я согласен с тобой, статический анализатор может выполнить любую проверку, которую может использовать компилятор. А в случае с Python этого должно быть достаточно.

Однако, если ваш компилятор достаточно сложный (особенно если у вас много прагм, которые меняют способ компиляции, или, например, Perl, вы можете запускать код во время компиляции), то статический анализатор должен подойти к сложности компилятора/интерпретатор для проведения анализа.

Хех, все эти разговоры о сложных компиляторах и запуске кода во время компиляции показывают мой фон в Perl.

Я понимаю, что Python не имеет прагм и не может запускать произвольный код во время компиляции. Итак, если я не ошибаюсь или эти функции не добавлены, достаточно простого анализатора в статическом анализаторе. Разумеется, было бы полезно принудительно выполнить эти проверки при каждом исполнении. Конечно, то, как я это делаю, - это прагма.

Как только вы добавите прагмы в микс, вы начали скользкий наклон, и сложность анализатора вашего анализатора должна возрастать пропорционально мощности и гибкости, которые вы предоставляете в своих прагмах. Если вы не будете осторожны, вы можете закончить как Perl, а затем "только python может разобрать Python", будущее, которое я бы не хотел видеть.

Возможно, переключатель командной строки был бы лучшим способом добавить принудительный статический анализ;)

(никоим образом не намерен оспаривать возможности Python, когда я говорю, что он не может работать с временем выполнения компиляции, как Perl. У меня есть догадка, что это тщательно продуманное дизайнерское решение, и я вижу мудрость в Это невероятная гибкость Perl во время компиляции, IMHO, большая сила и страшная слабость языка, я также вижу мудрость в этом подходе.)

+33
источник
другие ответы

Связанные вопросы


Похожие вопросы

У Python есть что-то, что может изменить синтаксис script:

from __future__ import print_function

и различные другие функции будущего, которые имеют синтаксические последствия. Это просто, что синтаксис Python был более строгим, более стабильным и более четким, чем исторический Perl; такие вещи, которые "строгие refs" и "строгие ограничения запрета" никогда не существовали в Python.

'строгие vars в первую очередь предназначены для остановки типизированных ссылок и пропущенных "mys" от создания случайных глобальных переменных (ну, переменных пакета в терминах Perl). Это не может произойти в Python, поскольку по умолчанию для локальных объявлений назначаются по умолчанию назначенные назначения, а голосные неназначенные символы приводят к исключению.

(По-прежнему существует случай, когда пользователи случайно пытаются выполнить сквозную запись в глобальный, не объявляя его "глобальным выражением", приводя к случайному локальному или, чаще, UnboundLocalError. Это, как правило, но это спорный случай, когда нужно было заявить, что ваши локальные жители могут помочь. Хотя мало опытных программистов на Python согласились бы с удобочитаемостью.)

Другие изменения языка и библиотеки, не связанные с синтаксисом, обрабатываются через систему warnings.

+11
источник

Я думаю, что есть некоторая путаница, как то, что "использует строгий", из комментариев, которые я вижу. Он не включает проверки типа времени компиляции (как Java). В этом смысле программисты Perl согласны с программистами python. Как говорит С.Лотт, эти типы проверок не защищают от логических ошибок, не уменьшают количество модульных тестов, которые вам нужно написать, и мы также не являемся крупными поклонниками программирования кабалов.

Здесь список того, что используется "use strict":

  • Использование символических ссылок - ошибка во время выполнения. Это мешает вам делать сумасшедшие (но иногда такие полезные вещи)

    $var = 'foo';

    $foo = 'bar';

    print $$var; # this would contain the contents of $foo unless run under strict

  • Использование необъявленных переменных - это ошибка времени выполнения (это означает, что вам нужно использовать "мой", "наш" или "локальный", чтобы объявить область переменной перед ее использованием.

  • Все простые слова считаются ошибками синтаксиса компиляции. Брейды - это слова, которые не были объявлены символами или подпрограммами. Это в основном для того, чтобы объявить вне закона то, что было исторически сделано, но считается ошибкой.

+7
источник

Python не имеет истинного лексического охвата, поэтому строгие vars не будут очень разумными. У него нет символических ссылок AFAIK, поэтому он не нуждается в строгих ссылках. У него нет ни единого слова, поэтому он не нуждается в строгих варах.

Честно говоря, это только лексическая область, которую я пропускаю. В двух других я бы подумал о бородавках в Perl.

+5
источник

Этот оригинальный ответ правильный, но, возможно, не объясняет ситуацию в практическом смысле.

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

В Perl используется "использование строгих" - это способность гарантировать, что неправильно написанный или имя переменной (обычно) попадает во время компиляции. Это улучшает код надежности и ускоряет разработку. Но для того, чтобы сделать такую ​​вещь стоящей, вам нужно объявить переменные. И стиль Python, кажется, препятствует этому.

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

Java и C/С++ делают это еще дальше, с проверкой типов. Мотивация практична, а не философски. Как вы можете как можно быстрее уловить как можно больше ошибок, и быть уверенным, что вы устраните все из них, прежде чем выпускать код для производства? Кажется, что каждый язык принимает конкретную стратегию и работает с ней, основываясь на том, что они думаю, важно. На языке Perl, где привязка времени выполнения не поддерживается, имеет смысл использовать "использовать строгую", чтобы упростить разработку.

+4
источник

Я считаю, что 'use strict' в Perl больше похож на прагму, на которую вы намекали: она изменяет поведение компилятора.

Философия языка Perl отличается от философии python. Как и в, вам дается более чем достаточно веревки, чтобы повесить себя неоднократно, на Perl.

Ларри Уолл большой в лингвистике, поэтому у нас есть Perl, что называется принципом TIMTOWTDI (скажем tim-toe-dee) против Zen python:

Должен быть один - и предпочтительно только один - простой способ сделать это.

вы можете очень легко использовать pylint и PyChecker, чтобы придумать свой собственный вкус use strict для python (или что-то аналогичное perl -cw *scriptname*), но из-за разных философий в дизайне языка вы не столкнетесь с этим в широко практикуются.

Основываясь на вашем комментарии к первому плакату, вы знакомы с python import this. Есть много вещей, которые освещают, почему вы не видите эквивалент use strict в Python. Если вы размышляете о коане, найденном в Дзен Питона, вы можете найти просветление для себя.:)

+3
источник

Я обнаружил, что мне действительно очень важно обнаруживать ссылки на необъявленные vars. Eclipse имеет интеграцию pylint через PyDev и, хотя pylint далек от совершенства, он делает разумную работу.

Это похоже на динамическую природу Python, и мне иногда приходится добавлять #IGNORE, когда мой код становится чем-то сообразительным. Но я нахожу, что это происходит нечасто, и я доволен этим.

Но я мог видеть, что полезность некоторых функций типа pylint становится доступной в виде флага командной строки. Вид вроде переключателя Python 2.6-3, который идентифицирует точки несовместимости между кодом Python 2.x и 3.x.

+1
источник

Очень сложно писать большие программы без "использования строгого" в Perl. Без "использования строгого" , если вы снова используете переменную и не заметите ее, оставив письмо, программа все еще работает. И без тестовых примеров для проверки ваших результатов вы никогда не сможете найти такие ошибки. По этой причине может потребоваться много времени, чтобы выяснить, почему вы получаете неправильные результаты.

Некоторые из моих программ Perl состоят из 5000 строк до 10 000 строк кода, разбитых на десятки модулей. Нельзя делать производственное программирование без "использования строгого" . Я бы никогда не разрешил устанавливать производственный код в factory с языками, которые не применяют "объявления переменных".

Вот почему Perl 5.12.x теперь использует "use strict" как поведение по умолчанию. Вы можете отключить их.

PHP дал мне немало проблем из-за отсутствия принудительного применения переменных. Поэтому вам нужно ограничить себя небольшими программами на этом языке.

Просто мнение...

abcParsing

+1
источник

Perl - это безудержный язык, как они сказали:). Таким образом, вы можете использовать переменную перед объявлением; Например: если вы используете имя var "is_array", но введите "is_arrby", компилятор не сообщит об ошибке без "использования строгой". Поэтому при кодировании длинной программы в perl лучше использовать инструкцию "use strict". Конечно, менее 50 строк для запуска один раз script, нет необходимости:)

0
источник

Кажется, что идеал кода "Pythonic" выполняет ту же цель, что и use strict.

-2
источник

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

-3
источник

Посмотрите другие вопросы по меткам или Задайте вопрос