Pull to refresh

Comments 25

Типы, как и читаемый код в целом, нужны не просто для других людей.

Через пару месяцев ты сам становишься "другим человеком"

Поражает, что питон, декларируя, что явное лучше неявного, полагается на неясность в выводе типов.

А Шаблоны или generic есть в пютоне? То-есть, в первой версии я вижу код, который складывает str значение двух любых типов.

Может и 1+2=12, может и [1,2] + [2,3]=[1,2][2,3], может и 1.2+2.3=1.22.3, а после добавление аннотации, код только с int начал работать, то-есть для float нужно писать второй раз такую функцию

~~~

А, дочитал, есть, ну ок

В свое время, до третьей версии питона, я отмечал ожидаемый тип переменной в имени переменной: temp__int, urls__list_str, updated_data__list_any, response__sparse_dict_int_str. Тип переменной именно суффиксом, а не префиксом, для удобства работы с автодополнением в редакторе. Также и для функций, тип возвратного значения заносится в имя.
Эти соглашения в readme потом пишутся одним абзацем. Вообще не о чем говорить, а польза большая. Хотя бы то, что ты явно задумываешься о типах переменных и можешь избежать оплошностей по неосторожности, которые всплыли бы потом, во время исполнения

С использованием аннотации ide тебе подскажет если ты накосячил, в вашем подходе нет такой фичи

а мы теперь вводим в него статическую типизацию

Аннотации типов это просто фича языка, которая позволяет вам более точно выразить ваши ожидания от типов.

def concat(a: int, b: int) -> str:
    return a+b

Как придумать еще один вариант записи комментариев, который может не отражать содержимого.

Аннотации типов нужны по большей части для самого программиста и IDE.

Интерпретатор сейчас их не валидирует никак - к огромному сожалению.

Но есть же mypy


К тому же я вроде бы несколько раз для ловил TypeError в рантайме

TypeError порождается операторами и встроенными функциями.

Нужны анализаторы. За такое они по рукам надают

Так можно вообще на любой язык набросить. Отстрелить себе намеренно ногу и публично предать язык анафеме: вот, ногу мне повредил.

ну так на базу нужно натравить тайп чекер. просто текст кода понятно что можно что угодно написать.

Я стараюсь документировать код, а аннотиции типов это самая легкая форма документации.
Есть поддержка со стороны языка и инструментов.

Забыли сказать про главную проблему типизации.
Если объект на тип который вы ссылаетесь, еще не определён, можно его тип взять в кавычки.

class Foo:
  def foo(self) -> "Foo":
    return self  

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

В данном случае я явно указываю свои ожидания, что возвращаемое значние менять не надо.

from typing import Mapping


def get_config() -> Mapping:
  config = {}  
  ...
  return config

Забыли сказать про главную проблему типизации.
Если объект на тип который вы ссылаетесь, еще не определён, можно его тип взять в кавычки.

Теперь в 3.10 можно указывать в методе класса, сам класс.

class Foo:
  def do_something() -> Foo:
		return Foo()

А в 3.11 нам завезут тип Self, который решает проблему типизации при наследовании, когда метод возвращает именно self, и у наследника это по сути будет уже другой тип.

from typing import TypeVar, Type

T = TypeVar('T')


class A:
    @classmethod
    def a(cls: Type[T]) -> T:
        return cls()

    def b(self: T) -> T:
        setattr(self, 'b_attr', True)
        return self


class B(A):
    def c(self) -> bool:
        return getattr(self, 'b_attr', False) or False

@ivanych

from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from some.other.module import SomeOtherType

    
def some_func(some_arg: 'SomeOtherType') -> bool: ...

В этом случае тайпхинт аргумента - строго ForwardReference (в кавычках, как строка).

UFO just landed and posted this here

Когда говорят о типах - примеры это всегда самое сложное.
Потому, что вы вводите типы, чтобы сделать код более хм... разумным.
Но когда вы приводите плохой пример - вы портите всё впечатление от разумных доводов.
Скажем вместо того, чтобы типизировать вот эту функцию - её просто (ровно в таком виде) не надо писать никогда:

def concat(a: int, b: int) -> str:
    return str(a) + str(b)



Т.е. может существовать либо "библиотечная" ф-ия:

def concat(a: str, b: str) -> str:
    return a + b
.....
x = concat(str(a), str(b))

Либо прикладная функция:

def getForm15Result(a: int, b: int) -> str:
    return str(a) + str(b)
UFO just landed and posted this here

Потому, что именование должно быть разумным.

Когда вы нарушаете правило разумного именования, а потом типизируете эту функцию - вы просто "заметаете проблемы под ковёр".

UFO just landed and posted this here
Аннотации плюс рефлексия позволяют делать чертовски изящные штуки со стороны библиотек. Пример — discord.py, либа для создания чат-ботов под Discord.
Там аннотации типов используются для прозрачного разбора и преобразования аргументов команды. Например:
@bot.command(pass_context=True)
def plus(context, x: int, y: int):
    context.send(f'{x} + {y} = {x+y}')

При вводе команды "!plus 2 3", библиотека попытается разбить строку на правильное число параметров и конвертировать их в нужные типы. Если получится — то вызовет обработчик plus() с правильными аргументами.
Для пользователя библиотеки это дико удобно, по-моему.

Динамичный питон до сих пор статично выдаёт ошибку при print( int(x) ), понятное дело, что это неправильный параметр для данной функции, да и с подобным в основном сталкиваются новички.


По основной теме:
питон динамичен, многие стараются делать универсальные функции для разных типов данных, особенно, если функция будет что-то перебирать. Порой проще добавить образно .to_list() , чем делать отдельную функцию под серию и под список.

Но, если не подразумеваются разные входные данные, то конечно вместо несколько строк описания - лучше просто сделать аннотацию.

Динамичный питон до сих пор статично выдаёт ошибку при print( int(x) )

Не выдает он уже давно никаких ошибок, для аргументов вызывается str

Sign up to leave a comment.