Комментарии 50
Вы про производительность программиста или скорость работы кода?
Чтобы не писать аннотации в код, можно использовать stub-файлы — файлы с расширением *.pyi
total=False
Ну и сам он не то, чтобы очень удобен в эксплуатация — каждый вложенный словарь тоже должен объявляться отдельно как TypedDict
А зачем именно словари, когда есть namedtuple и dataclass?
По моему опыту обычно отсутствие поля в json считают эквивалентным null в качестве значения.
from .types import ImageJson
image: ImageJson = {
"src": "/image.jpg",
"srcset": {
"@2x": "/image@2x.jpg"
}
}
Для таких ситуаций для python до 3.7 подходит TypedDict из mypy_extensions
from typing import Dict
from mypy_extensions import TypedDict
ImageJson = TypedDict('ImageJson', {
'src': str,
'srcset': Dict[str, str]
})
А в python 3.7 появились dataclass и лучше использовать их.
Опять же, почему не dataclass?
@dataclass
class Image:
src: str
srcset: Dict[str, str]
Делал, кстати, себе небольшую либу для разбора словарей в инстансы датаклассов, которая как раз юзает аннотации типов для правильной инициализации.
Поправил свой комментарий выше.
Для 3.6 датаклассы есть в виде библиотеки. typehints по сути тоже с 3.6
И, кстати, в 3.6 есть NamedTuple, хотя его я никогда не юзал.
class Employee(NamedTuple):
src: str
srcset: Dict[str, str]
Mypy работает даже в 2.7 (они так говорят, я не проверял), т.е. уже в 2.7 можно использовать typehints.
В дополнение к этому, для внедрения typehints в проекты, где изначально не было ни typehints ни dataclass, проще создать тип для словаря и его указать, чем переделывать со словарей на dataclass.
Я полностью согласен с тем, что новые проекты желательно делать на 3.7 и с dataclass и прочими прелестями, но есть применение и для TypedDict.
А что значит неизменяемый?
>>> class Employee(NamedTuple):
... src: str
... srcset: Dict[str, str]
...
>>> e = Employee(src="1", srcset={"2": "4"})
>>> e.srcset["2"] = "7"
>>> e.srcset["4"] = "17"
>>> e
Employee(src='1', srcset={'2': '7', '4': '17'})
>>>
Работает в том числе и на python 2.7
Хм. Похоже, чистая динамическая типизация вымирает. PHP, Python, Ruby — все языки обрастают типами. Да и JavaScript уже заменяется на TypeScript'ы всякие. Любопытная картина.
Первый вариант использую когда нужно быстро накидать скрипты (1-2 файла = 1 задача), где и так понятно что должно происходить, какие данные будут, и т.д., второй вариант — когда делается проект.
Например:
def get_certificate_san(x509cert):
san = ''
ext_count = x509cert.get_extension_count()
for i in range(0, ext_count):
ext = x509cert.get_extension(i)
if 'subjectAltName' in str(ext.get_short_name()):
san = ext.__str__()
return san
Как проще всего узнать тип ext_count? Нет, я могу, конечно весь код усеять print(type(variable)) и потом выписать вручную. Но как-то выглядит некрасиво. А типы иногда бывают неочевидными, если просто смотреть на код.
UPD
Нашел в PyCharm раздел, который это описывает. Интересно) www.jetbrains.com/help/pycharm/type-hinting-in-product.html
Наверно, я немножко опоздал с ответом, но в подобной ситуации тип x509cert
по идее должен быть заранее известен тому, кто пишет эту функцию. Беглый гуглинг подсказывает, что скорее всего подразумевается что-то вроде этого:
from OpenSSL.crypto import X509
def get_certificate_san(x509cert: X509) -> str:
ext_count = x509cert.get_extension_count()
# ...
Дальше, если в библиотеке прописаны аннотации путей или если они очевидно выводятся, PyCharm и другие статические анализаторы автоматически догадаются, что метод get_extension_count()
у класса X509
возвращает int
и что ext_count
будет иметь соответствующий тип, без дополнительных подсказок.
К сожалению, конкретно pyOpenSSL, похоже, немного поленился прописать аннотации типов у себя (и в typeshed прописано не всё), так что работать это наверно будет плоховато (и я не в курсе, умеет ли кто-нибудь вытаскивать типы из docstring'ов)
Проверки во время разработки.
Код станет сложнее читать, если раньше ты мог быстро просмотреть код, то теперь тебе приходится больше его расшифровывать.
А зачем что-то расшифровывать?
Представьте тысячи строк кода, с указанием типов…
А что их представлять, я их каждый день вижу.
Наоборот, код без аннотаций придётся расшифровывать, тщательно вчитываясь в код и угадывая, какой же там тип получается на выходе.
Прописываешь аннотации правильно и не нужно с длинными переменными возиться ;)
Очень даже помогает, потому что можно просто сходить и почитать аннотации у функции, результат которой помещается в обсуждаемую переменную. Без аннотаций придётся читать такую функцию целиком, выясняя, какие же типы она может вернуть. В особо запущенных случаях функция возвращает результат вызова другой функции, и я так по цепочке могу на полчаса зарыться в исходники какой-то библиотеки на гитхабе, выясняя, какой же там блин тип. Особенно если к функции написана хреновая документация (таким грешат даже «взрослые» проекты вроде Django)
Подскажите кто-нибудь, почему в Python 3.11 перестали работать предупреждения при использовании неверных типов, для словарей в частности. Т.е. вот этот код из статьи исполняется без каких-либо ошибок и предупреждений. Не могу понять, как так...
from typing import Dict
book_authors: Dict[str, str] = {”Fahrenheit 451”: “Bradbury”}
book_authors[“1984”] = 0 # Incompatible types in assignment (expression has type “int”, target has type “str”)
book_authors[1984] = “Orwell” # Invalid index type “int” for “Dict[str, str]”; expected type “str”
print(book_authors)
# Выводит {'Fahrenheit 451': 'Bradbury', '1984': 0, 1984: 'Orwell'} без каких‑либо ошибок и предупреждений.
Введение в аннотации типов Python