Если вы работаете над большим проектом на Python или предпочитаете лаконичную и понятную базу кода, то Pytype станет для вас отличным помощником.
Python — это отличный язык программирования для создания скриптов и прототипов. Емкий синтаксис, гибкая система типов и хорошая интерпретируемость помогают быстро опробовать идею, скорректировать ее и попробовать еще раз.
В процессе роста проекта гибкость, которая когда-то обеспечивала быстроту работы, становится тяжким бременем, замедляющим разработку. Когда к проекту подключаются другие разработчики, пишется больше кода. А нехватка информации по типам осложняет чтение и понимание кода. Без системы проверки типов легко допустить ошибки. Но вот отловить их будет не так-то просто.
Pytype спешит на помощь! Pytype — это open-source инструмент для проверки и вывода типов в Python. К тому же, это уже готовое решение — установите и приступайте к работе!
Pytype может:
- Статистически выводить информацию о типах и проверять код на ошибки в типах.
- Проверять согласованность аннотаций типов PEP 484.
- При необходимости возвращать выведенную информацию о типах.
Если вы уже заинтересовались, то установите Pytype и следуйте инструкциям. Ниже приведены полезные примеры использования.
Пример 1: Вывод и проверка типа
Это самый популярный сценарий. Вы пишите код и хотите проверить его на наличие ошибок. Присмотритесь к этой функции:
import re def GetUsername(email_address): match = re.match(r'([^@]+)@example.com', email_address) return match.group(1)
Тут все понятно. Она использует регулярное выражение для извлечения части адреса электронной почты до @ и возвращает его. А вы заметили ошибку?
Давайте посмотрим, что нам скажет pytype :
% pytype get_username.py Analyzing 1 sources with 0 dependencies File "/.../get_username.py", line 5, in GetUsername: No attribute 'group' on None [attribute-error] In Optional[Match[str]]
Pytype говорит нам, что group не является допустимым вызовом функции для match. При отсутствии совпадений re.match() возвращает None. И действительно, в данных случаях match.group(1) выбросит исключение.
Давайте устраним ошибку, сделав так, чтобы для некорректного адреса почты функция возвращала None:
import re def GetUsername(email_address): match = re.match(r'([^@]+)@example.com', email_address) if match is None: return None return match.group(1) # <-- Here, match can't be None
Теперь, когда мы вновь запустим pytype, ошибка не обнаружится. Pytype предполагает, что при выполнении кода после if, match точно не окажется None.
Пример 2: Проверка аннотации типов
В Python 3 вам доступна аннотация типов (PEP 484). Так вы сможете лучше донести свою мысль до средств проверки типов и других разработчиков. Pytype предупреждает об ошибках в аннотации типов:
import re from typing import Match def GetEmailMatch(email) -> Match: return re.match(r'([^@]+)@example.com', email)
Давайте проверим этот фрагмент кода через pytype:
% pytype example.py Analyzing 1 sources with 0 dependencies File "/.../example.py", line 5, in GetEmailMatch: bad option in return type [bad-return-type] Expected: Match Actually returned: None
Pytype сообщает, что GetEmailMatch может вернуть None. Но мы задали его возвращаемый тип как Match. Для исправления ошибки можно прибегнуть к аннотации типа Optional из модуля typing:
import re from typing import Match, Optional def GetEmailMatch(email) -> Optional[Match]: return re.match(r'([^@]+)@example.com', email)
Optional означает, что возвращаемое значение может быть объектом Match или None.
Пример 3: Возвращение информации о выведенных типах
Чтобы лучше освоиться в аннотациях типов, Pytype может добавлять их в сам код. Давайте рассмотрим этот фрагмент:
import re def GetEmailMatch(email): return re.match(r'([^@]+)@example.com', email) def GetUsername(email_address): match = GetEmailMatch(email_address) if match is None: return None return match.group(1)
Перед добавлением аннотации типов сначала запускаем pytype для файла. pytype сохраняет информацию о выведенном типе в файле.pyi. Затем мы можем вернуть аннотации типов в код через запуск merge-pyi:
% pytype email.py % merge-pyi -i email.py pytype_output/email.pyi
Вуаля!
import re from typing import Match from typing import Optional def GetEmailMatch(email) -> Optional[Match[str]]: return re.match(r'([^@]+)@example.com', email) def GetUsername(email_address) -> Optional[str]: match = GetEmailMatch(email_address) if match is None: return None return match.group(1)
Аннотации типов, включая выражения import, теперь присутствуют в исходном файле.
Специально для сайта ITWORLD.UZ. Новость взята с сайта NOP::Nuances of programming