Aspiring Data Science
373 subscribers
425 photos
11 videos
10 files
1.87K links
Заметки экономиста о программировании, прогнозировании и принятии решений, научном методе познания.
Контакт: @fingoldo

I call myself a data scientist because I know just enough math, economics & programming to be dangerous.
Download Telegram
#python #codegems #typing #cleancode

Пример применения всратых средств типизации Питон.

Предположим, что требуется создать функцию top(it, n), которая возвращает n наибольших элементов из итерируемого объекта it:

>>> top([4, 1, 5, 2, 6, 7, 3], 3)
[7, 6, 5]
>>> l = 'mango pear apple kiwi banana'.split()
>>> top(l, 3)
['pear', 'mango', 'kiwi']
>>>
>>> l2 = [(len(s), s) for s in l]
>>> l2
[(5, 'mango'), (4, 'pear'), (5, 'apple'), (4, 'kiwi'), (6,
'banana')]
>>> top(l2, 3)
[(6, 'banana'), (5, 'mango'), (5, 'apple')]

как же такую функцию "правильно" аннотировать?

Казалось бы, можно сделать через TypeVar так:
from typing import TypeVar
T = TypeVar('T')

def top(series: Iterable[T], length: int) -> list[T]:
ordered = sorted(series, reverse=True)
return ordered[:length]

Вопрос в том, как ограничить T. Это не может быть Any или object, потому что series должен работать с функцией sorted.
Правильное, типа, решение - объявить протокол, поддерживающий операцию сравнения (для сортировки):

from typing import Protocol, Any
class SupportsLessThan(Protocol):
def __lt__(self, other: Any) -> bool: ...


и уже потом ограничить TypeVar этим протоколом:

LT = TypeVar('LT', bound=SupportsLessThan)
def top(series: Iterable[LT], length: int) -> list[LT]:
ordered = sorted(series, reverse=True)
return ordered[:length]

Ну и типа сидишь такой, думаешь: а стоит ли прохождение проверок типов mypy этих усилий, дополнительного кода, введённых несовместимостей? Я, честно, ХЗ.
#python #books #typing #cleancode

В книжке Fluent Python пишут:

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

Даже в тех контекстах, где статическая типизация наиболее полезна, на нее нельзя полагаться как на единственный критерий правильности. Вполне можно столкнуться с:
Ложноположительными результатами
Инструмент сообщает об ошибке, когда ее нет.

Ложноотрицательными результатами
Инструмент не сообщает об ошибке в заведомо неправильном коде.

Кроме того, требуя проверять типы всего на свете, мы утрачиваем часть выразительности Python:

некоторые удобные возможности нельзя проверить статически, например распаковку аргументов вида config(**settings);

программы проверки типов в общем случае плохо поддерживают или вообще не понимают таких продвинутых возможностей, как свойства, дескрипторы, метаклассы и метапрограммирование;

программы проверки типов не поспевают за выходом новых версий Python, отвергают код, содержащий новые возможности, или даже «падают» – и иногда это продолжается больше года.

Самые простые ограничения на данные невозможно выразить в системе типов. Например, аннотации типов не могут гарантировать, что «величина должна быть целым числом > 0» или что «метка должна быть строкой длиной от 6 до 12 символов ASCII». Вообще, аннотации слабо помогают отлавливать ошибки в прикладной логике.

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

Рассматривайте программы статической проверки типов как один из инструментов в современном конвейере непрерывной интеграции (CI) наряду с автоматизированными тестами, линтерами и т. д. Цель конвейера CI – уменьшить количество программных ошибок, а автоматизированные тесты находят многие ошибки, выходящие за рамки возможного для аннотаций типов. Любой код, который можно написать на Python, можно на Python и протестировать – с аннотациями типов или без них."

"Я сам большой поклонник тестирования, но при этом часто занимаюсь исследовательским кодированием. Во время экспериментов тесты и аннотации типов не особенно полезны. Они только тормозят работу."

"Если кодинг – не ваша профессия, а лишь полезный инструмент, применяемый в профессиональных занятиях, или нечто такое, что вы изучаете ради удовольствия, то, пожалуй, аннотации типов нужны вам не больше, чем жесткие ботинки и металлические набойки большинству велосипедистов.
Просто кодируйте."

"Я согласен, что пользователи большинства API выигрывают от наличия аннотаций типов. Но Python привлекал меня – среди многих других причин – тем, что предоставляет чрезвычайно мощные функции, способные заменить целые API, и, более того, мы сами можем писать такие функции.

Рассмотрим встроенную функцию max(). Она мощная, но понять ее легко. Однако, как будет показано в разделе «Перегрузка max», чтобы ее правильно аннотировать, нужно 14 строчек аннотаций типов, и это не считая typing.Protocol и нескольких определений TypeVar, необходимых для поддержки этих аннотаций.

Я боюсь, что если библиотеки будут строго требовать аннотирования типов, то программисты раз и навсегда зарекутся писать такие функции."
#python #typing #cleancode

Ну и вдогонку.

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

Настаивая на вставке аннотаций везде и всюду, мы теряем часть выразительности Python. Такие замечательные средства, как распаковка аргументов - например, config(**settings), – выходят за пределы возможностей программ проверки типов.

Если вы хотите подвергнуть вызов вида config(**settings) проверке типов, то должны будете выписать каждый аргумент. Это наводит меня на воспоминания о Turbo Pascal, на котором я писал 35 лет назад.

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

Спасибо Гвидо за факультативную типизацию. Давайте будем использовать ее так, как она задумана, и не пытаться аннотировать все вокруг в строгом соответствии со стилем кодирования, напоминающим Java 1.5."

В общем, нужно найти баланс между всратостью и разумностью )
#python #typing

Про Final не знал. Self, TypeAlias, Literal заслуживают внимания.
На самом деле всё ещё сложнее с TypeVar.

https://medium.com/techtofreedom/8-levels-of-using-type-hints-in-python-a6717e28f8fd
👀1