Что такое type hinting как работает зачем нужен
Тайп-хинтинг по всем канонам полиморфизма в старых версиях PHP
tl;dr Вкратце, в данной статье я создам трейт, позволяющий даже в версиях PHP младше 5.6 (до версии 5.4) добиться от компилятора поведения, подобного любому статическому языку программирования. Причём трейт будет валидировать не только входные, но и выходные парамеры тоже. Так сказать, полное погружение в тайп-хинтинг.
Данный трейт вы сможете без проблем подключить и использовать в своих веб-приложениях.
Тайп-хинтинг в PHP версии старше 7.0
З.Ы. Я специально написал валидацию каждого примитива по отдельности, чтобы в дальнейшем была возможность передать в трейт массив со своими дополнительными правилами валидации. Например для integer-а можно провалидировать maxValue, minValue, isNatural, для строк можно валидировать length вместо emptiness и так далее.
Используется трейт очень просто. В качестве примера реализуем класс Notebook, хранящий в себе методы генерации и получения уникального идентификатора для того, чтобы показать, как можно с помощью данного трейта проверять входные и выходные данные функции.
Ещё один пример: класс Pen (простая чернильная ручка, инициализирующаяся с каким-то количеством чернил), выводящий сообщение на экран.
Ну а теперь давайте распишем нашу ручку на столе: «Hello World»!
Заключение
Вот с помощью такого вот простенького трейта можно из слона сделать си-шарп валидировать входные/выходные параметры функций без копипастинга методов в разных классах.
Я специально не стал прикручивать к методу validate() в примере выше особые параметры валидации, например такие, как минимальное/максимальное значение double-ов или строковых переменных, пользовательские колбэки на валидацию параметров, вывод своего сообщения при выбросе исключения и так далее.
Потому что основной целью статьи было рассказать о том, что технология, позволяющая добиться от языка статичности, есть и легко реализуема она даже на старой версии PHP.
Тип Хинтинг в PHP
Начиная с PHP 5, вы можете использовать подсказку типа, чтобы указать ожидаемый тип данных аргумента в объявлении функции. Когда вы вызываете функцию, PHP проверит, имеют ли аргументы заданный тип. Если нет, время выполнения вызовет ошибку и выполнение будет остановлено.
Допустимые типы — это имена классов для аргументов, которые получают объекты, и массив для тех, которые получают массивы. Вот пример:
Точно сообщая PHP, какие объекты ожидает метод enroll() Точно так же вы знаете, что у вас не будет никаких упрямых пахидерм, появляющихся в первый день третьего класса.
Что произойдет, если я попытаюсь поступить в Medicare?
Несмотря на то, что я студент, произойдет следующая ошибка:
Если Нулевое значение используется в качестве значения по умолчанию для аргумента, это также будет разрешено. Вот пример, на этот раз с массивами:
Там будет вечеринка, пока есть гости, с едой или без.
Ограничения хинтинга
Любой определенный класс может быть допустимой подсказкой типа, хотя PHP не поддерживает подсказки типа для универсального объекта. А как насчет всего остального?
Вот своеобразный пример ограничений хинтинга типов в PHP:
Вы не первый думаете: «Что это за безумие? Я дал вам экземпляр строки, и все же вы жалуетесь, что это должен быть экземпляр строки! »Все в порядке. Это случается с лучшими из нас. На самом деле, это может быть довольно
сбивающее с толку сообщение об ошибке на первый взгляд.
stringTest() string Скалярные типы данных, такие как строки или целочисленные значения, не поддерживаются в подсказках типа PHP. Но это нормально! Если вам нужно вызвать ошибку или выдать исключение, когда аргумент не является скалярным типом (например, строка или целое число), вы можете выполнить базовую проверку для этой цели, используя такие функции, как is_string() is_int()
Скалярные войны
Было немного противоречий относительно добавления скалярной подсказки типа PHP в PHP 5.4. Те, кто выступает против изменений, утверждают, что эта поддержка будет идти против фундаментальных конструкций PHP. PHP считается слабым типизированным языком. По сути, это означает, что PHP не требует, чтобы вы объявляли типы данных. С переменными по-прежнему связаны типы данных, но вы можете делать радикальные вещи, такие как добавление строки к целому числу, не приводя к ошибке.
В мае 2010 года в транк PHP была добавлена поддержка хинтинга скалярного типа. Но из-за реакции сообщества эта функция не появится в версии 5.4.
Резюме
Подсказка типов — это методика, введенная в PHP для объектно-ориентированного программирования (особенно для определения типа перехваченного исключения). Я рекомендую вам прочитать больше о работе с объектами здесь.
Описание типов — PHP: Основы программирования
Когда мы пишем на PHP, то не особо задумываемся над типами данных. Мы просто пишем код и ожидаем, что данные будут соответствовать нашим ожиданиям:
Чтобы объявить тип аргумента, необходимо перед его именем добавить имя требуемого типа:
Null не похож на другие типы данных и ведет себя особым образом. Типы данных в PHP не являются nullable, это значит, что если мы ждем на вход значение определенного типа, например, строку, то этим значением не может быть Null, но, если указать значение, по умолчанию равное Null, то указанный тип становится nullable и появится возможность передавать Null снаружи.
Не nullable
nullable
С версии PHP 7.2 появилась возможность указывать тип не только для входящих параметров, но и для возврата функции. Оно записывается через двоеточие после закрывающей скобки:
Если ошибиться в теле функции выше и вернуть строку, то интерпретатор скажет об этом:
В общем и целом, этот механизм никак не влияет на сам процесс программирования и стиль кодирования. Основные его плюсы проявляются в тех местах, где идет работа с классами и интерфейсами, но этот вопрос мы затронем позже, в курсах, посвященных объектно-ориентированному программированию.
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты.
Русские Блоги
Полностью понять подсказки типов в Python (Type Hints)
Как все мы знаем, Python является динамически типизированным языком, и тип переменной не нужно указывать во время выполнения. Это не изменится, но в сентябре 2015 года основатель Гвидо ван Россум представил систему типов в Python 3.5, которая позволяет разработчикам указывать типы переменных. Его основная функция заключается в облегчении разработки, используемой IDE и различными инструментами разработки, и не влияет на выполнение кода, а также будет фильтровать информацию о типах во время выполнения.
Одним из главных преимуществ Python является то, что он динамически набирается, и это не изменится. И в сентябре 2014 годаGuido van Rossum (Python BDFL) Создано предложение по улучшению Python (PEP-484), Добавить подсказки типа (Type Hints) для Python. И через год он был выпущен как часть Python 3.5.0 в сентябре 2015 года. Так дляДвадцать пять летPython, есть стандартный способ добавить информацию о типе в код. В этой записи блога я расскажу о том, как развивается система, как мы ее используем и каков следующий шаг для подсказки типов.
Зачем вам нужны подсказки типа?
Преимущества подсказок типа
Во-первых, давайте посмотрим, зачем нам нужны подсказки типов в Python. Типовые подсказки имеют много преимуществ, и я постараюсь перечислить их в порядке важности:
Легко понять код
Понимание типов параметров может облегчить понимание и поддержку базы кода.
Например, теперь есть функция. Хотя мы знали типы параметров при создании функции, это уже не так в течение нескольких месяцев. Типы и возвращаемые типы всех параметров указаны рядом с кодом, что может значительно ускорить процесс понимания этого фрагмента кода. Всегда помните код, который вы читаете, гораздо больше, чем код, который вы пишете. Поэтому вам следует оптимизировать функцию для удобства чтения.
С помощью подсказок типов вы можете указать, какие типы параметров вам нужно передать при вызове функции, а когда вам нужно расширить / изменить функцию, вам также сообщат типы данных, необходимые для ввода и вывода. Например, представьте следующую функцию, которая отправляет запрос,
Просто глядя на сигнатуру этой функции, мы можем узнать:
Фактически, многие из нас уже понимают, что предоставление информации о типе в коде крайне важно. Однако из-за отсутствия лучших опций информация о типе в коде часто упоминается в документации.
Система подсказок типов может перемещать информацию о типе из документа в интерфейс ближе к функции, а затем объявлять требования к сложным типам в четко определенном виде. В то же время, создавая линтеры и запуская их после каждого изменения кода, вы можете проверить эти ограничения на подсказки типов, чтобы убедиться, что они никогда не устаревают.
lint относится к инструментам статического анализа кода
Легко рефакторинг
Тип подсказка может помочь нам найти класс лучше при рефакторинге.
Хотя многие IDE теперь предоставляют эту функцию с использованием некоторой эвристики, подсказки типов могут сделать 100% Точность обнаружения и определения местоположения класса. Это сделает более плавным и точным определение того, как тип переменной работает в коде.
Помните, что хотя динамическая типизация означает, что любая переменная может быть любого типа, все переменные должны всегда иметь только один тип. Система типов по-прежнему является ключевым компонентом программирования, подумайте о тех, кто использует isinstance Определите время, потраченное на переменные типы и логику приложения.
Простая в использовании библиотека
Использование подсказок типа означает, что в среде IDE может быть более точный и умный механизм рекомендаций. При вызове автозаполнения среда IDE будет знать с полной уверенностью, какие методы / свойства доступны для объекта. Кроме того, если пользователь пытается вызвать несуществующий контент или передать неверный тип параметра, среда IDE может немедленно предупредить об этом.
Type Linters
Хотя среда IDE предупреждает о неправильных типах параметров, целесообразно использовать инструмент linter для расширения этой функции, чтобы обеспечить логический тип приложения. Такие инструменты могут помочь вам обнаружить ошибки как можно раньше (например, пример после ввода должен иметь тип str, а передача None вызовет исключение):
Хотя в этом примере некоторые люди могут подумать, что несоответствие типов параметров легко увидеть, но в более сложных случаях это несоответствие становится все труднее увидеть. Например, вложенные вызовы функций:
Проверьте рабочие данные
Подсказки типа могут использоваться для проверки во время выполнения, чтобы гарантировать, что вызывающая сторона не нарушает соглашения метода. Больше нет необходимости использовать длинный список утверждений типа в начале функции, вместо этого мы можем использовать платформу, которая повторно использует подсказки типов и автоматически проверяет, удовлетворяются ли они до запуска бизнес-логики (например, используяpydantic):
Что не может сделать определение типа?
С самого начала Гвидо ясно дал понять, что подсказки типов не предназначены для использования в следующих случаях использования (конечно, это не означает, что нет такой библиотеки / инструментов):
Нет вывода типа времени выполнения
Интерпретатор времени выполнения (CPython) не пытается выводить информацию о типе во время выполнения или проверять параметры, переданные на основании этого.
Нет настройки производительности
Интерпретатор времени выполнения (CPython) не использует информацию о типе для оптимизации сгенерированного байт-кода для обеспечения безопасности или производительности.
При выполнении скрипта Python подсказки типов обрабатываются как комментарии, и интерпретатор автоматически их игнорирует.
Какой тип системы нужен?
Python имеет прогрессивные подсказки типов, что означает, что независимо от того, когда для данной функции или переменной подсказка типа не указана.
Можно предположить, что он может иметь любой тип (т.е. он все еще является частью динамического типа).
И постепенно информируйте вашу кодовую базу о типах, например, об одной функции или переменной за раз:
Помните, только код с подсказками типа будет проверен на тип!
Когда вы запускаете linter (например, mypy) в коде с подсказками типов, в случае несоответствия типов возникает ошибка:
Этот код выдаст следующий вывод:
Обратите внимание, что мы можем обнаружить несовместимость типов входящих параметров и атрибутов доступа, которые не существуют в объекте. Последний может даже предоставить эффективные варианты, облегчая обнаружение и исправление орфографических ошибок.
Как добавить информацию о типе
Как только вы решите добавить подсказку типа, вы обнаружите, что она может быть добавлена в базу кода разными способами.
Type annotations
Типовые аннотации (Типовые аннотации) являются прямым способом и наиболее распространенным способом в типовых документах.
ИспользуетсяPEP-3107(Python 3.0+) Добавить аннотации функций и передатьPEP-526(Python 3.6+) Добавлены переменные аннотации. Это может сделать при написании кода,
Преимущества этого метода:
Таким образом, установлено, что последние два пункта противоречат начальным целям системы типов, которые мы перечислили ранее:
То есть в основном все типы информации обрабатываются как комментарии во время выполнения.
Чтобы разрешить эти противоречия, Python 3.7 представилPEP-563
Добавьте следующее утверждение, интерпретатор больше не будет создавать эти составные типы.
После того, как интерпретатор проанализирует синтаксическое дерево скрипта, он распознает подсказку типа и пропустит его оценку, оставив его в качестве исходной строки. Этот механизм заставляет подсказки типа происходить там, где они необходимы: проверка типа с помощью linter В Python 4 этот механизм станет поведением по умолчанию.
Type comments
Когда аннотации (аннотации типов) недоступны, вы можете использовать аннотации типов:
Пройдя по этому пути, мы получили некоторые преимущества:
Тип аннотации применяются к любой версии Python.
Хотя библиотека типов была добавлена в стандартную библиотеку в Python 3.5+, она может использоваться как пакет PyPi для Python 2.7+. Кроме того, поскольку комментарии Python являются допустимой языковой функцией для любого кода Python, вы можете добавить подсказки типов в код на Python 2.7 или более поздней версии. Есть некоторые требования: комментарий подсказки типа должен быть в той же или следующей строке, где находится определение функции / переменной. Это также type: постоянные пуски.
Это решение также решает проблему упаковки, потому что комментарии редко удаляются. Подсказки типов пакетов в исходном коде могут позволить тем, кто использует разрабатываемые вами библиотеки, использовать подсказки типов для улучшения своего опыта разработки.
Но это также создает некоторые новые проблемы:
Чтобы избежать длинных строк кода в качестве подсказок типа, вы можете добавить параметры подсказки один за другим через комментарии типа, а затем поместить код после комментариев возвращаемого типа:
Давайте кратко рассмотрим, как аннотации типов делают код более запутанным.
Вот фрагмент кода, который обменивает два значения атрибута в классе:
Во-первых, вы должны добавить подсказку типа.
Поскольку подсказки типа могут быть очень длинными, вы можете прикрепить параметры подсказки типа через параметры:
Но подождите, пока не добавите используемый тип:
Теперь такой код будет вызывать некоторые ложные срабатывания в статическом линтере (например, pylint), поэтому для этого нужно добавить несколько комментариев подавления:
Это теперь завершено. Затем шесть строк кода становятся шестнадцатью строками, и необходимо поддерживать больше кода!
Если вам платят за количество строк кода, которые вы пишете, и менеджер жалуется на вашу низкую производительность в последнее время, то добавление базы кода звучит хорошо.
Interface stub files
Таким образом, код поддерживается следующим образом:
В отличие от других методов, этот метод добавляет другой файл pyi рядом с исходным файлом:
Интерфейсные файлы не новы, C / C ++ использовался десятилетиями.
Поскольку Python является интерпретируемым языком, он обычно не нужен, но поскольку любую проблему в информатике можно решить, добавив новый косвенный слой, мы можем добавить его для хранения информации о типах.
Конечно, есть некоторые относительно большие расходы:
Чтобы решить эти проблемы, первоначальный автор взял на себя задачу объединения заглушки с исходным файлом в mypy. Теоретически, эти две проблемы могут быть решены.python/mypy
issue 5208Проверьте прогресс в.
Docstrings
Вы также можете добавить информацию о типе в строку документа. Несмотря на то, что это не является частью инфраструктуры хинтинга типов, разработанной для Python, она поддерживается большинством основных IDE. Использование этого метода в основном традиционное.
С положительной стороны:
Тем не менее, он имеет серьезные недостатки в следующих формах:
Какого типа информация должна быть добавлена
Давайте углубимся в конкретные детали. Полный список типов, которые можно добавить, см. ВОфициальные документы, Здесь я дам вам краткий 3-минутный обзор, чтобы понять это.
Существует два типа классификации: номинальные типы и типы утки (протоколы).
Nominal type
PHP Type Hints
Summary: in this tutorial, you’ll learn how to use PHP type hints to declare the types for function parameters and return values.
Introduction to PHP type hints
PHP is a dynamically typed language. When you define a function, you don’t need to declare types for parameters. For example:
The add() function accepts two arguments and returns the sum of them. In this example, we pass two integers into the add() function and get the result as an integer.
If you pass two floating-point numbers into the add() function, you’ll get the sum of the floats, which is a floating-point number:
More interestingly, you can pass an integer and a numeric string into the add() function, it will return an integer:
In this case, the add() function implicitly coerces the numeric string ‘2’ into the integer 2 because of the + operator. If PHP fails to coerce the string argument into an integer, it’ll issue an error. For example:
To enforce the types for function parameters and return value, you can use type hints.
Note that PHP also allows you to use type hints for class properties and methods which you’ll learn in the PHP object-oriented programming tutorial.
PHP type hints for function parameters
The type hints ensure that PHP will check the type of a value at the call time and throw a TypeError if there is a mismatch.
To add a type hint to a parameter, you place a type in front of it like this:
The following defines the add() function that accepts two integers:
However, if you pass two floats, you’ll get the result as an integer:
In this case, PHP implicitly coerces 2.5 into an integer ( 2 ) before calculating the sum. Therefore, the result is an integer.
By default, PHP coerces a value of the compatible type into the expected scalar type declaration if possible. To enforce the value with a type that matches the type declaration, you need to declare strict typing.
PHP type hints for function’s return value
To specify a return value’s type for a function, you add the type after the function header like this:
The following example defines the add() function that accepts two integers and returns an integer:
Starting from PHP 7.0, if a function doesn’t return a value, you use the void type. For example:
The union type
Starting from PHP 8.0, if a function returns a value of several types, you can declare it as a union type. For example:
In this example, the add() function returns an integer or a floating-point number, depending on the types of arguments.
The mixed type
If a function returns a value of many types, you can use the mixed type. The mixed type means one of several types. The mixed type. It’s equivalent to the following union type:
The mixed has been available since PHP 8.0.0.
For example, the filter_var() built-in function use both union type (array|int) and mixed type as the type hints:
The nullable type
The following defines a function that accepts a string and returns the uppercase of that string:
If you pass an argument with null, you’ll get an error:
The nullable type was introduced in PHP 7.1.
Note that the mixed type already includes the null type. Therefore, you don’t need to include nullable mixed like this: