Безопасен ли тип Python?

Согласно Википедии

Ученые-информатики считают язык типобезопасным, если он не допускает операций или преобразований, нарушающих правила системы типов.

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

То же самое говорят Джейсон Орендорф и Джим Бланди в Программирование на Rust :

Обратите внимание, что безопасность типов не зависит от того, проверяет ли язык типы во время компиляции или во время выполнения: C проверяет во время компиляции и не является типобезопасным; Python проверяет во время выполнения и является типобезопасным.

Обе отдельные концепции статической проверки типов и безопасности типов.

Это правильно?


person user8664060    schedule 24.09.2017    source источник
comment
python - это язык для утиного набора текста. Если он ходит как утка, звучит как утка и выглядит как утка - это утка. Я бы не сказал, что это типобезопасно - проверьте этот поток stackoverflow.com/questions/4205130/what- is-duck-typing   -  person Chen A.    schedule 24.09.2017
comment
Да, набор текста может быть статическим или динамическим. язык может быть типобезопасным или небезопасным. C статически типизирован, но ни в коем случае не является типобезопасным.   -  person juanpa.arrivillaga    schedule 24.09.2017
comment
@Vinny: Я не думаю, что утиная печать имеет отношение к этой дискуссии. Мне Python кажется безопасным по типу: '1' + 2. Например, Javascript не является типобезопасным.   -  person Eric Duminil    schedule 24.09.2017
comment
@EricDuminil на основе инструкции из википедии a language is "type-safe" if it does not allow operations or conversions that violate the rules of the type system. В вашем примере выполняется автоматическое преобразование. Попробуйте сделать это с объектами, определяемыми пользователем. Типобезопасность означает, что вы указываете типы переменных и не можете использовать их, если не переопределите явное значение. В python вы можете сделать это: s = 'this is string'; s = 1 но вы не можете сделать это в Java   -  person Chen A.    schedule 24.09.2017
comment
@Vinny: В примере, который я привожу для Python, автоматическое преобразование не выполняется: возникает исключение. В ваших примерах показана только разница между статической и динамической типизацией, которая также не имеет отношения к вопросу.   -  person Eric Duminil    schedule 24.09.2017
comment
@EricDuminil gotcha. Вы правы, я перепутал два. Спасибо   -  person Chen A.    schedule 24.09.2017
comment
@Vinny: Нет проблем, я люблю быть невыносимым всезнайкой! : D   -  person Eric Duminil    schedule 24.09.2017
comment
chan: это простой пример недопустимых вариаций семантики / типов в одной и той же области: s = 1; s = привет. но когда дело доходит до функций с нетипизированными возвращаемыми значениями и нетипизированными параметрами, это добавляет оскорбления к травме. кроме того, классы с недостаточной защитой видимости, неявно невозможным полиморфизмом, список намного длиннее ... ничего плохого с python, просто не используйте его в больших проектах, или если вы действительно будете строги и попросите достаточно времени, чтобы написать избыточный тестовые примеры (для всех возможных типов). этого никогда не бывает в производстве   -  person Dan Marinescu    schedule 31.07.2020
comment
смешивание типов одного и того же идентификатора в одной и той же области так же плохо, как и визуальный базовый ... но эй, это еще не все, потоки ... глобальная блокировка интерпретатора и другие вещи, которые хуже, чем небезопасность типов, только парни, такие как Билл, могут терпеть и продавать   -  person Dan Marinescu    schedule 31.07.2020


Ответы (8)


Многие программисты приравнивают статическую проверку типов к безопасности типов:

  • язык A имеет статическую проверку типов, поэтому он является типобезопасным
  • язык B имеет динамическую проверку типов, поэтому он небезопасен

К сожалению, не все так просто.

В реальном мире

Например, C и C ++ небезопасны по типам, потому что вы можете подорвать систему типов с помощью каламбура типа. Кроме того, спецификации языка C / C ++ в значительной степени разрешают неопределенное поведение (UB), а не явно обработки ошибок, и это стало источником уязвимостей безопасности, таких как эксплойт разбивания стека и атака строки формата. Такие эксплойты не должны быть возможны в типобезопасных языках. В ранних версиях Java была ошибка типа с его Generics, который доказал, что это не полностью типобезопасный.

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

[Wikipedia] С другой стороны, многие языки слишком велики для доказательства безопасности типов, созданные человеком, так как они часто требуют проверки тысяч случаев. .... определенные ошибки могут возникать во время выполнения из-за ошибок в реализации или в связанных библиотеках, написанных на других языках; такие ошибки могут сделать данный тип реализации небезопасным при определенных обстоятельствах.

В Академии

Типовая безопасность и системы типов, хотя и применимы к реальному программированию, имеют свои корни и определения, взятые из академических кругов < / em> - и поэтому формальное определение того, что именно является безопасностью типов, сопряжено с трудностями, особенно когда речь идет о реальных языках программирования, используемых в реальном мире. Ученые любят математически (формально) определять крошечные языки программирования, называемые игрушечными языками. Только для этих языков можно формально показать, что они безопасны по типу (и доказать, что операции логически верны).

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

Например, ученые изо всех сил пытались доказать типобезопасность Java, поэтому они создали уменьшенную версию под названием Featherweight Java и доказали это в paper, что он является типобезопасным. Точно так же этот Ph.D. paper Кристофера Лайона Андерсон взял подмножество Javascript, назвал его JS0 и доказал, что он безопасен по типу.

Практически предполагается, что правильные языки, такие как python, java, c ++, не являются полностью типобезопасными, потому что они такие большие. Крошечный жучок так легко проскользнет сквозь трещины, которые подорвут систему типов.

Резюме

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

Ссылки: http://www.pl-enthusiast.net/2014/08/05/type-safety/ и https://en.wikipedia.org/wiki/Type_system

person James Lawson    schedule 24.09.2017
comment
Практически предполагается, что правильные языки, такие как ... c ++, не являются полностью типобезопасными - мы можем точно сказать, что это небезопасно по типу, верно? Это просто ошибка? - person user8664060; 03.10.2017
comment
Практически любой язык с динамической типизацией обеспечивает безопасность типов за счет динамической проверки типов перед доступом к содержимому переменной. Так что они безопасны по типу. Ни одна из ваших ссылок не объясняет, почему языки со статической типизацией обычно безопаснее. Я не знаю ни одного популярного небезопасного языка с динамической типизацией, но как минимум два языка со статической типизацией (C / C ++). - person CoronA; 03.10.2017
comment
Ваше последнее утверждение в резюме просто неверно. безопасность типов, поскольку не имеет ничего общего со статической или динамической типизацией. Python не является типобезопасным, если вы используете ctypes. - person Daniel; 09.10.2017
comment
подрывать систему типов с помощью каламбура. как это подрывает систему типов? - person curiousguy; 26.11.2017
comment
Интересный. На днях я наткнулся на Pony (ponylang.io) и сказал, что у него есть математическое доказательство безопасности типов. и я не понимал, почему это было важно. Доказательство, которое они предоставили: ponylang.io/media/papers/fast -cheap-with-proof.pdf - person Jerry Jeremiah; 31.10.2019
comment
Резюме просто вводит в заблуждение (вероятно, намеренно) и совершенно неверно. Нет ничего безопасного, когда плохой программист (без надлежащих инженерных знаний / формального образования и опыта) создает дешевые импровизации, переворачивая счета. Помимо этого, компилятор - ваш друг. компиляторы экономят ваше бесценное время на правильное модульное тестирование и тестирование покрытия. без них продукт небезопасен для надлежащего обслуживания и неявно так же ценен, как входной барьер на определенных языках (НОЛЬ). я очень люблю питона, не воспринимайте мои слова плохо! - person Dan Marinescu; 31.07.2020
comment
Поскольку вы сказали, что академические круги не указывают точно, что такое безопасность типов, позвольте мне помочь: тип, с которым может происходить определенный набор значений и операций. компилятор - это процесс, переводящий единицы компиляции (обычно написанные людьми, но не всегда) с одного языка на другой. если компилятор постоянно проверяет целостность типа и не допускает переопределения с другой семантикой в ​​самой области видимости, он считается типобезопасным. утиная печать небезопасна по типу, потому что это происходит во время выполнения - person Dan Marinescu; 31.07.2020
comment
кроме того, интерпретатор python можно рассматривать как компилятор на лету, способный компилировать и фактически выполнять по одной строке за раз, конечно, в области / контексте (зная, какие другие типы и значения доступны в любое время, в течение это однострочное исполнение). Достаточно было бы добавить обязательство объявлять переменную с ее точным типом, прежде чем можно будет ее использовать (начиная с python ONE), и это было бы лучше (для всей планеты было бы лучше). но дух был в том, чтобы снизить входной барьер почти до нуля, чтобы средний Джо мог набрать 1 + 1 и пойти как 2 - person Dan Marinescu; 31.07.2020
comment
но наем посредственных программистов (вместо инженеров-программистов) - источник всего зла, больше, чем отсутствие безопасности типов (я считаю) - person Dan Marinescu; 31.07.2020

Статья в Википедии связывает безопасный тип с безопасным для памяти, что означает, что к одной и той же области памяти нельзя получить доступ, например, целое число и строка. Таким образом, Python является типобезопасным. Вы не можете неявно изменить тип объекта.

person Daniel    schedule 24.09.2017
comment
но вы можете изменить его явно, в той же области, что напоминает мне быстрый базовый :-) - person Dan Marinescu; 31.07.2020

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

Вы можете вручную обеспечить безопасность типов в своих программах, проверив типы входных данных. Поскольку все является объектом, вы всегда можете создавать классы, производные от базовых классов, и использовать функцию isinstance для проверки типа (конечно, во время выполнения). Python 3 добавил подсказки типов, но это не применяется. И mypy добавил статическую проверку типа в язык, если вы хотите его использовать, но это не гарантирует тип безопасность.

person VoNWooDSoN    schedule 03.10.2017
comment
отложить это до последнего момента означает: - person Dan Marinescu; 31.07.2020
comment
2. Последний момент в большинстве случаев испытывают клиенты (на уже развернутом продукте, с особыми обстоятельствами / проблемами) - person Dan Marinescu; 31.07.2020
comment
3. Модульные тесты, в которых вы явно используете динамический запрос метаданных (isinstance), не могут охватывать какие-либо определенные пользователем типы данных, которые частично синтаксически соответствуют определенному контексту выполнения, и вот почему: просто потому, что нельзя использовать isintance для типов данных, которые не существуют в то время, когда на самом деле происходит testcase и вызов isinstance. а вы как то ходите?!? Что ж, представьте себе: сегодня вы вручную добавляете всевозможные проверки isinstance к тысячам тестовых примеров. но они не будут хорошими, если (в будущем) кто-то добавит новые совместимые типы данных без корректировки всех тестовых примеров - person Dan Marinescu; 31.07.2020
comment
mypy не является основным питоном - person Dan Marinescu; 31.07.2020
comment
должна быть возможность применять намеки в жизнь, но, как всегда, доброжелательный диктатор (не в отставке) не видел этого так. это также объясняет полный отказ python 2 vs python 3 - person Dan Marinescu; 31.07.2020
comment
Последний момент в сообществе иногда называют «утиной печатью» и обычно считают функцией. Вместо того, чтобы принудительно вводить типы (через типы), исключения возникают при попытке вызова метода или оператора для типа, который не реализует его во время выполнения. Таким образом, интерфейсы (см. Модуль abc) не нужно разрабатывать и реализовывать до написания программы, а унаследованный код можно расширять или исправлять, чтобы добавить только необходимые функции, чтобы данные соответствовали алгоритму. - person VoNWooDSoN; 13.08.2020

Не в твоих самых смелых мечтах.

#!/usr/bin/python

counter = 100          # An integer assignment
miles   = 1000.0       # A floating point
name    = "John"       # A string

print counter
print miles
print name

counter = "Mary had a little lamb"

print counter

Когда вы запустите это, вы увидите:

python p1.py
100
1000.0
John
Mary had a little lamb

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

В реальном мире профессиональной разработки программного обеспечения под безопасным типом мы подразумеваем то, что компилятор улавливает глупые вещи. Да, в C / C ++ вы можете предпринять чрезвычайные меры для обхода безопасности типов. Вы можете объявить что-то вроде этого

union BAD_UNION
{
   long number;
   char str[4];
} data;

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

Программист может делать неприятные вещи с приведением типов в C / C ++, но они должны делать это намеренно; не случайно.

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

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

Рассмотрите возможность использования инсулиновой или инфузионной помпы. Что-то, что закачивает ограниченное количество спасающих / продлевающих жизнь химикатов в человеческий организм с желаемой скоростью / интервалом.

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

person user3450148    schedule 03.11.2020

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

>>> 'a' + 1

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

Поскольку эта проверка выполняется только во время выполнения, а не перед запуском программы, Python не является типизированным языком (PEP-484 несмотря на это).

person Mureinik    schedule 24.09.2017
comment
Это все еще определенное поведение, которое не нарушает правила системы типов, не так ли? - person user8664060; 24.09.2017
comment
Насколько я могу судить, нет требования, чтобы проверка типа не могла выполняться во время выполнения. В самом деле, как говорится в статье в Википедии, принудительное применение типов может быть статическим, обнаруживая потенциальные ошибки во время компиляции, или динамическим, связывая информацию о типе со значениями во время выполнения и консультируясь с ними по мере необходимости для обнаружения неизбежных ошибок, или их комбинацию. - person juanpa.arrivillaga; 24.09.2017
comment
Python не компилируется - person whackamadoodle3000; 05.10.2017
comment
@ whackamadoodle3000: все широко используемые реализации Python являются компиляторами. - person Daniel; 09.10.2017
comment
Если он не позволяет нарушить систему типов, он безопасен по типу - не имеет значения, когда это произойдет. Проверка статического типа не гарантирует, что он безопасен по типу (см. C и c ++) - person Jerry Jeremiah; 31.10.2019
comment
и лучший пример того, что происходит во время выполнения, прост: не вы и / или qa поймаете это, а ВАШИ КЛИЕНТЫ. мило да? - person Dan Marinescu; 31.07.2020
comment
подсказки, определенные / описанные в pep-484, великолепны, но если вы случайно их прочитаете, вы увидите, что никаких проверок нет даже во время выполнения. Так что лучше использовать статический анализатор, чем ничего! - person Dan Marinescu; 31.07.2020

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

3 оси масштабируемости:

  1. время сборки (возможность спроектировать и изготовить безопасные системы в срок и бюджет)
  2. время выполнения (очевидно)
  3. поддерживать время (способность поддерживать (исправлять ошибки) и расширять существующие системы безопасным способом, как правило, путем рефакторинга)

единственный способ сделать безопасный рефакторинг - это полностью протестировать все (используйте разработку, управляемую тестами, или хотя бы модульное тестирование, а также хотя бы достойное тестирование покрытия, это не qa, это development / r & d). то, что не покрыто, сломается, и подобные системы - скорее мусор, чем инженерные артефакты.

Теперь предположим, что у нас есть простая функция sum, возвращающая сумму двух чисел. можно представить себе выполнение модульного тестирования этой функции, основываясь на том факте, что известны как параметры, так и возвращаемый тип. мы не говорим о шаблонах функций, которые сводятся к тривиальному примеру. напишите простой модульный тест для той же функции с именем sum, где параметры и возвращаемый тип могут быть буквально любого типа, они могут быть целыми числами, числами с плавающей запятой, строками и / или любыми другими типами, определяемыми пользователем, с перегруженным / реализованным оператором плюс . как написать такой простой тестовый пример?!? насколько сложным должен быть тестовый пример, чтобы охватить все возможные сценарии?

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

иди разбери! :-)

person Community    schedule 30.07.2020

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

  1. наивный ответ: компилятор - ваш друг. несмотря на то, что ему около 65 лет, это правда, и эй, дело не только в статических типах! ide (s) используют службы компилятора для множества вещей, которые для среднего программиста Джо выглядят как магия ... (завершение кода, помощь во время разработки (редактирование) и т. д.
  2. o более реальная причина заключается в чем-то совершенно неизвестном разработчикам, не имеющим большого опыта в области компьютерных наук и, более того, в разработке программного обеспечения. Есть 3 оси масштабируемости: a. разработка / написание и развертывание, b. время выполнения и т. д. поддерживать время на основе рефакторинга. Как вы думаете, кто самый дорогой? явно повторяется в любой реальной серьезной системе? третий (с). чтобы удовлетворить (c), вам нужно сделать это безопасно. Для того, чтобы выполнить безопасный рефакторинг, вам необходимо пройти модульное тестирование И тестирование покрытия (чтобы вы могли оценить уровень покрытия, охватываемый вашим набором модульного тестирования) - помните, что когда что-то не тестируется автоматически, оно сломается (во время выполнения, в конце цикла, на сайте клиента, вы называете это) - Итак, чтобы иметь достойный продукт, вам нужно иметь достойное модульное тестирование и покрытие тестами

А теперь перейдем к нашей интеллектуальной функции (сумме). is sum (a, b) не указывает типы a и b, нет возможности провести достойное модульное тестирование. такие тесты, как assent sum (1,1), равны 2 IS ЛОЖЬ, потому что они не охватывают ничего, кроме предполагаемых целочисленных аргументов. в реальной жизни, когда a и b являются гермафродитами типа, тогда нет никакого способа написать реальное модульное тестирование против суммы функций! различные фреймворки даже делают вид, что получают результаты тестового покрытия из урезанных тестовых примеров, подобных описанному выше. это (очевидно) еще одна ЛОЖЬ.

это все, что я должен был сказать! спасибо за чтение, единственная причина, по которой я это опубликовал, это, возможно, для того, чтобы вы подумали об этом и, может быть (МОЖЕТ БЫТЬ ...) однажды заняться разработкой программного обеспечения ...

person Community    schedule 27.11.2020

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

   if sys.errno:
        my_favorite_files.append(sys.errno)

вместо этого:

    if args.errno:
        my_favorite_files.append(sys.errno)

Агрессивное преобразование чего-либо в Boolean, потому что оно упрощает if операторы, - это то, чего я не ожидал найти в языке, который является типобезопасным.

person vy32    schedule 30.12.2020