0. Предисловие
Я проанализировал в предыдущей статьеПочему Python не пустотный типПо теме , после публикации статьи читатель обсуждал со мной еще один вопрос о жанре, однако вскоре у нас возникли серьезные разногласия.
Наши основные отличия:Является ли Python строго типизированным языком?Я так думаю, а он думает, что нет.
Он написал очень длинную статью»Кто вам сказал, что Python — строго типизированный язык! Встань и пообещай не бить тебя!, конкретно подтверждающий его точку зрения, но, к сожалению, полный ошибок и упущений.
У меня была идея написать о типах Python, и теперь я воспользуюсь случаем, чтобы систематизировать это.
(PS: Когда я был где-то на полпути к написанию, в читательской аудитории WeChat случилось обсуждение темы «сильных и слабых типов»! При обсуждении с вами некоторые мои идеи были проверены, а также я узнал много новых Знаний. , так что часть содержания этой статьи имеет кредит группы друзей, спасибо!)
1. Динамические и статические типы, сильные и слабые типы
Многие читатели должны быть знакомы с动态类型и静态类型, но многие люди также связывают их с强弱类型Это сбивает с толку, поэтому сначала нам необходимо сделать некоторые концептуальные пояснения.
Оба набора типов специфичны для языков программирования, но фокусируются на разных основных проблемах.
Для концепции «динамических и статических типов» основным вопросом является «когда вы знаете, какой тип переменной»?
Вообще говоря, язык со статической типизацией определяет тип переменной во время компиляции, а язык с динамической типизацией определяет тип переменной во время выполнения.
Например, функция "int func(int a){...}" определена в некоторых языках, и ее параметры и возвращаемое значение можно определить во время компиляции, чтобы знать, что ее параметры и возвращаемые значения имеют тип int. , так что это статический тип, хотя, как правило, такое как Python, определение При написании "def func(a):..." при написании функции я не знаю типы параметров и возвращаемых значений. Только когда функция вызывается во время выполнения, могут ли быть окончательно определены типы параметров и возвращаемых значений, поэтому это динамический тип.
Для концепции «сильных и слабых типов» основным вопросом является «Допускают ли переменные разных типов неявные преобразования»?
В общем, у компиляторов есть строго типизированные языки с небольшим количеством (разумных) неявных преобразований и слабо типизированные языки с большим количеством (чрезмерных) неявных преобразований.
Например, в Javascript"1000"+1получит строку «10001», а"1000"-1Будет получено число 999, то есть компилятор выполняет неявное преобразование типов для двух разных типов объектов в зависимости от случая использования, но аналогичные методы записи будут сообщать об ошибке типа в строго типизированном языке. (Преобразование чисел и строк является чрезмерным преобразованием, и некоторые разумные преобразования будут упомянуты ниже.)
В соответствии с приведенным выше определением кто-то нарисовал классификационную диаграмму распространенных языков программирования:

По делению размерностей сильного и слабого типа можно сделать вывод, что:
- Строгая типизация: Java, C#, Python, Ruby, Erlang (плюс GO, Rust)…
- Слабая типизация: C, C++, Javascript, Perl, PHP, VB...
2. Понятие о сильных и слабых типах в прошлом
Концепция динамических и статических типов в основном признается всеми, однако концепция сильных и слабых типов вызывает много споров в сообществах вопросов и ответов, технических форумах и академических дискуссиях. Здесь он не будет указан.
Почему так много споров?
Одна из основных причин заключается в том, что кто-то смешал его со статическим типом.
Самый очевидный пример — интервью, проведенное Гвидо ван Россумом в 2003 году, в котором речь шла о сильных и слабых типах (Strong versus Weak Typing):

Однако то, о чем они явно говорят, так это о разнице в типе движения и неподвижности.
В интервью также цитировались слова Джеймса Гослинга, отца Java, из его выражения видно, что «сильный и слабый тип», о котором он говорил, на самом деле является различием между динамическими и статическими типами.
Есть и классический пример: Деннис Ритчи, отец языка C, однажды сказал, что язык C — это «строго типизированный, но слабо проверяемый» язык. Если сравнивать с предыдущим определением, то он фактически относится к «статически типизированным слабо типизированным».
Почему эти большие парни сбиты с толку?
Причина на самом деле очень проста,То есть в то время не существовало четкого разграничения понятия динамического типа, сильного и слабого типа! Другими словами, сильный и слабый тип в это время относится к динамическому и статическому типу.
Википедия дает определение строго типизированного в Википедии 1970 года, которое можно свести к ранее упомянутому статическому типу:
In 1974, Liskov and Zilles defined a strongly-typed language as one in which "whenever an object is passed from a calling function to a called function, its type must be compatible with the type declared in the called function."[3] In 1977, Jackson wrote, "In a strongly typed language each data area will have a distinct type and each process will state its communication requirements in terms of these types."[4]
Аналогичная концепция должна быть у отцов предыдущих языков программирования.
Однако большие парни также понимали, что понятие «сильный и слабый тип» в то время было недостаточно точным, поэтому Деннис Ритчи говорил об этом как ** «сильный тип, но слабый чек»,И в интервью Гвидо также подчеркнул, что Python не следует называть слаботипизированным, а следует говорить, что онввод во время выполнения** .
Но в те ранние дни сильный и слабый типы были в основном такими же, как и динамические типы, и эта идея до сих пор затрагивает многих людей.
3. Текущая концепция сильных и слабых типов
Ранняя классификация языков программирования на самом деле представляет собой смесь динамических и сильных и слабых измерений.Однако они не являются однозначным соответствием и перекрытием, и их недостаточно, чтобы выразить различие между языками программирования.Поэтому это необходимо иметь более явное/богатое определение.
Некоторые люди предложили различать параметры, такие как «безопасность типов» и «безопасность памяти», а также существуют типы статической проверки и типы динамической проверки, которые имеют определенное пересечение с сильными и слабыми типами.
До 2004 года интеграционные академические документы»Type Systems(от Microsoft Research Луки Карделли), которая специализируется на различных системах типов для языков программирования:

Краткое изложение проверки прочности (то есть типа прочности) в документе выглядит следующим образом:
- Strongly checked language: A language where no forbidden errors can occur at run time (depending on the definition of forbidden error).
- Weakly checked language: A language that is statically checked but provides no clear guarantee of absence of execution errors.
Главное, что программаuntrapped errorsСила проверки, в некоторых местах, которые действительно пошли не так, слабо типизированные программы не фиксируют обработку, такую как некоторые вычисления указателя и преобразования в языке C, и "Десять заповедей для программистов на C«Первые несколько — это проблемы, вызванные слабыми типами.

Определение этих понятий в статье относительно абстрактно.Поскольку большинство неотловленных ошибок вызвано неявным преобразованием типов, определение в первом разделе эволюционировало, и неявное преобразование типов используется в качестве стандарта суждения.
Сегодня «терпимость к неявным преобразованиям типов» используется в качестве стандарта классификации сильных и слабых типов, и это уже является консенсусом многих людей (хотя и недостаточно полным, и есть разные мнения).
Например, Википедия называет неявное преобразование типов одной из основных особенностей слабой типизации:
A weakly typed language has looser typing rules and may produce unpredictable results or may perform implicit type conversion at runtime.
Например, взяв в качестве примера Python,Основное мнение сообщества состоит в том, что это строго типизированный язык, и стандартом суждения также является рассмотрение неявного преобразования типов.
Есть много примеров, таких как официальный Python Wiki, который конкретно отвечаетWhy is Python a dynamic language and also a strongly typed language, дает 4 ответа, характеризующих «динамически строгую типизацию» Python:

В качестве другого примера, в разноплановой беседе в главе 11 «Fluent Python» также особо упоминается классификация сильных и слабых типов. (Его термин — «несколько неявных преобразований типов», что является более строгим, но также неправильно классифицирует C++ как строго типизированный.)
4. Является ли Python строго типизированным языком?
На тему «является ли Python строго типизированным» до сих пор существует много недоразумений, выходящих за рамки общепринятого мнения.
С одной стороны, некоторые люди используют смесь сильных и слабых типов, а также динамических и статических типов, для этого есть исторические причины, которые были проанализированы ранее.
Существует также не менее важная причина, по которой некоторые люди приравнивают слабую типизацию к «полному отсутствию неявного преобразования типов», что неверно.
На самом деле концепция сильных и слабых типов содержит некоторые релятивистские последствия, и в строго типизированных языках также могут быть неявные преобразования типов.
Например, язык Rust разработал очень мощную систему типов, чтобы реализовать философию проектирования «безопасности памяти», но в нем также есть неявное преобразование типов (автоматическое разыменование).
Проблема в:Какое неявное преобразование типов допустимо? Кроме того, является ли неявное преобразование типов некоторых поверхностей действительно неявным преобразованием типов?
Возвращаясь к примеру с Python, мы можем проанализировать несколько типичных вариантов использования.
Например,"test"*3Эта операция «умножения» строк, хотя и является двумя типами операций, не требует неявного преобразования типа.
Например,x=10; x="test"Назначайте разные типы переменной один за другим. На первый взгляд, тип x изменился. Вы можете использовать type(x), чтобы оценить разницу. Однако тип в Python привязан к значению (привязка rvalue), а не к привязке переменных.
Переменная x — это просто имя переменной, если быть точным, метка, привязанная к фактической переменной, она не имеет типа. Type(x) определяет не тип самого x, а тип объекта, на который указывает x, точно так же, как встроенная функция id(x) вычисляет не адрес самого x, а адрес фактического объект.
Например,1 + TrueЭто добавление чисел к логическим типам также не имеет неявных преобразований типов. Поскольку тип boolean в Python на самом деле является подклассом целого числа, тот же самый тип! (Если сомневаетесь, см.PEP-285)
Другой пример: добавление целочисленного/логического значения к числу с плавающей запятой не требует явного преобразования типов в Python. Однако в процессе его реализации на самом деле используются числа__add__()Методы, все в Python - это объект, и числовые объекты также имеют свои собственные методы. (Не обязательно на других языках)
Это,Арифметическая операция между числами на самом деле представляет собой процесс вызова функции, который принципиально отличается от арифметических операций в других языках.
Кроме того, хотя различные числовые типы сильно различаются на уровне памяти компьютера, в глазах людей они относятся к одному и тому же типу (в широком смысле), поэтому даже если происходит неявное преобразование типов, оно логически приемлемо.
Наконец, есть пример проверки правды Python после if/while , который я проанализировал ранее.Принцип реализации, который преобразует другие типы объектов в логические значения.
Однако на самом деле это всего лишь результат вызова функции (__bool__() и __len__()), который является разумным результатом, полученным вычислением, а не неявным приведением, и не относится к категории неотловленных ошибок.
Итак, строго говоря, в предыдущих 5 примерах не происходит никакого преобразования типов.Примеры чисел с плавающей запятой и оценок истинности интуитивно представляют собой преобразования типов, но на самом деле они являются управляемыми функциями Python, которые соответствуют ожиданиям и не наносят ущерба исходным типам.
Сделав шаг назад, если ослабить значение «неявного преобразования типов», считается, что неявное преобразование типов происходит в последних двух примерах, однако они реализуются через строгий процесс вызова функций, и запрещенных ошибок не будет. , поэтому они по-прежнему относятся к строго проверенным типам.
5. Другие сопутствующие вопросы
В предыдущей статье был сделан подробный анализ значения концепции и ее производительности в Python. Далее для полноты логики и темы нам необходимо ответить на несколько небольших вопросов:
(1) Можно ли использовать «неявное преобразование типов» в качестве основы для классификации сильных и слабых типов?
Определение четкого классификации должно начинаться сType Systems"Субъект, у него есть набор классификаций для разных ошибок, а сильный и слабый типы на самом деле являются классификациями обработки для запрещенных ошибок. Неявное преобразование типов — его очевидная особенность, но это еще не все и не единственная основа для суждения.
Чтобы облегчить понимание, в этой статье используется эта основная функция для разделения сильных и слабых типов, но следует подчеркнуть, что сильные типы не имеют неявных преобразований типов, но могут иметь несколько разумных неявных преобразований типов.
(2) Если существуют другие интерпретаторы, позволяющие Python поддерживать широкий спектр неявных преобразований типов, остается ли Python строго типизированным языком?
Стандартная спецификация языка подобна закону, а интерпретатор является исполнителем. Если есть неправильная интерпретация правоприменения, то закон остается тем же законом, и неправильное правоприменительное поведение должно быть исправлено; если есть проблема с самим законом (вызывает двусмысленность и противоречие в толковании, или от него следует отказаться ), то закон следует пересмотреть, чтобы обеспечить его определение Пола (сильно типизированного или слаботипизированного).
(3) Почему Javascript является слабым типом?
Потому что его неявное преобразование типов очень, очень сложно, очень избыточно! Например, в Javascript123 + nullРезультат 123,123 + {} Результатом является строка «123[object Object]».
Кроме того, его двойной знак равенства "==" может иметь несколько неявных преобразований типов в дополнение к базовым операциям сравнения, таким какtrue==['2']Результат судебного решения является ложным, иtrue==['1']Результат верный и[]==![]и[undefined]==falseВсе результаты соответствуют действительности...
(4) C ++ слабо напечатанный язык?
Я упомянул, что C++ строго типизирован в Fluent Python, но на самом деле его следует классифицировать как слабо типизированный. Преобразование типов в C++ — очень сложная тема. Мисс @yingyulou написала серию статей для ее систематического обсуждения. Адрес статьи:Как преодолеть сложные преобразования типов в C++?,Подробно объясните неявное преобразование типов и перегрузку функций в C++!,Кто сказал, что приведения C++ трудно понять?
6. Резюме
Концепция сильных и слабых типов вызывает много споров в Интернете не только в Python, но и в таких языках, как C/C++.
На самом деле, академически это понятие уже четко определено, и фактически оно было принято многими людьми.
Те, кто возражал, были в основном из-за концептуального смешения, потому что они игнорировали другой аспект категоризации языков; в то же время также стоило отметить, что строгая типизация не может считаться равной «отсутствию неявного преобразования типов вообще» или «при условии, что так как нет неявного преобразования типа xxx".
В этой статье представлена основная классификация Python в сообществе и анализируется использование нескольких предполагаемых неявных преобразований типов, демонстрирующих, что это строго типизированный язык.
В статье воплощена последовательная пытливость автора, заключающаяся в том, что «Почему Python«Серия стилей, если вам нравится эта статья, подпишитесь!
Ссылки по теме
[1] Кто вам сказал, что Python — строго типизированный язык! Встань и пообещай не бить тебя! :blog.CSDN.net/Парень из Nokia/AR…
[2] Strong versus Weak Typing: Woohoo. Aretima.com/int V/strong…
[3] En. Wikipedia.org/wiki/strong…
[4] En. Wikipedia.org/wiki/strong…
[5] Type Systems: Этика Лу Чачи.Тогда /papers/type…
[6] Десять заповедей для программистов C:doc.cat - V.org/ легко_заставить извергать...
[7] Why is Python a dynamic language and also a strongly typed language: wiki.Python.org/MO в/почему%20…
[8] PEP-285: GitHub.com/Китайский макияж…
[9] Type Systems: Этика Лу Чачи.Тогда /papers/type…
[10] Почему Python:GitHub.com/Китайский макияж…