Вопрос

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

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

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

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

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


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

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

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

    FOO = 12
    foo += 3
    

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

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

  • используйте строгие заменители:Реального аналога в Python нет.

Это было полезно?

Решение

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

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

Вот, по сути, и все.Инструменты статического анализа недостаточно помогают Python, чтобы быть полезными.


Редактировать

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

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

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

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

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

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

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

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

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

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

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

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

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

Другие советы

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

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

Строгие переменные (одна из опций для strict в 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 является неопределенным.Но только тогда, когда код выполнен.Если ваш набор тестов не имеет 100% покрытия, вы можете легко устранить эту ошибку.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

(Ни в коем случае не ставлю под сомнение возможности Python, когда я говорю, что он не может работать во время компиляции, как это может Perl.У меня есть предчувствие, что это тщательно продуманное дизайнерское решение, и я вижу в нем мудрость.Чрезвычайная гибкость Perl во время компиляции, ИМХО, является большой силой и ужасной слабостью языка;Я также вижу мудрость в таком подходе.)

У Python действительно есть что-то, что может изменить синтаксис скрипта:

from __future__ import print_function

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

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

(Все еще существует случай, когда пользователи случайно пытаются выполнить запись в глобальный файл, не объявляя его с помощью оператора ‘global’, вызывая либо случайный локальный, либо, чаще, UnboundLocalError.Как правило, этому учатся довольно быстро, но это спорный случай, когда необходимость объявлять своих местных жителей может помочь.Хотя немногие опытные программисты на Python согласились бы взять на себя бремя удобочитаемости.)

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

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

Вот список того, что делает "use strict"::

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

    $var = 'foo';

    $foo = 'bar';

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ABC - анализ

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

Похоже, что идеальный "питонический" код служит во многом той же цели, что и use strict.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top