Другие ответы хорошо объяснили типизацию утки и простой ответ от tzot :
Python не имеет переменных, как и в других языках, где переменные имеют тип и значение; у него есть имена, указывающие на объекты, которые знают их тип.
Однако , одна интересная вещь изменилась с 2010 года (когда вопрос был задан впервые), а именно реализация PEP 3107 (реализована в Python 3). Теперь вы можете фактически указать тип параметра и тип возвращаемого типа функции следующим образом:
def pick(l: list, index: int) -> int:
return l[index]
Здесь мы видим, что pick
принимает 2 параметра, список l
и целое число index
. Также должно возвращаться целое число.
Таким образом, здесь подразумевается, что l
- это список целых чисел, которые мы можем увидеть без особых усилий, но для более сложных функций это может немного сбить с толку относительно того, что этот список должен содержать. Мы также хотим, чтобы значение по умолчанию index
было равно 0. Чтобы решить эту проблему, вы можете написать pick
следующим образом:
def pick(l: "list of ints", index: int = 0) -> int:
return l[index]
Обратите внимание, что теперь мы помещаем строку как тип l
, что синтаксически разрешено, но не подходит для программного анализа (к которому мы вернемся позже).
Важно отметить, что Python не будет поднимать TypeError
, если вы передадите число с плавающей точкой в index
, причина этого - один из основных моментов в философии дизайна Python: "Мы все согласные взрослые здесь ", что означает, что вы должны знать, что вы можете передать функции, а что нет. Если вы действительно хотите написать код, который выдает TypeErrors, вы можете использовать функцию isinstance
, чтобы проверить, что переданный аргумент имеет правильный тип или подкласс этого типа:
def pick(l: list, index: int = 0) -> int:
if not isinstance(l, list):
raise TypeError
return l[index]
Подробнее о том, почему вы должны делать это редко, и о том, что вы должны делать вместо этого, говорится в следующем разделе и в комментариях.
PEP 3107 не только улучшает удобочитаемость кода, но также имеет несколько подходящих вариантов использования, о которых вы можете прочитать здесь .
В Python 3.5 аннотации типов получили гораздо больше внимания благодаря введению PEP 484 , в котором представлен стандартный модуль для подсказок типов.
Эти подсказки о типах пришли из проверки типов mypy ( GitHub ), которая теперь PEP 484 соответствует.
С модулем набора текста поставляется довольно обширная коллекция подсказок типа, в том числе:
List
, Tuple
, Set
, Map
- для list
, tuple
, set
и map
соответственно.
Iterable
- полезно для генераторов.
Any
- когда это может быть что угодно.
Union
- когда это может быть что-либо в указанном наборе типов, в отличие от Any
.
Optional
- когда может быть None. Сокращение для Union[T, None]
.
TypeVar
- используется с дженериками.
Callable
- используется в основном для функций, но может использоваться для других функций.
Это наиболее распространенные типовые подсказки. Полный список можно найти в документации для модуля ввода .
Вот старый пример с использованием методов аннотации, введенных в модуле ввода:
from typing import List
def pick(l: List[int], index: int) -> int:
return l[index]
Одной из мощных функций является Callable
, которая позволяет вам вводить аннотированные методы, которые принимают функцию в качестве аргумента. Например:
from typing import Callable, Any, Iterable
def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
"""An immediate version of map, don't pass it any infinite iterables!"""
return list(map(f, l))
Приведенный выше пример мог бы стать более точным с использованием TypeVar
вместо Any
, но это было оставлено читателю в качестве упражнения, поскольку я считаю, что я уже наполнил свой ответ слишком большой информацией о замечательные новые функции, включенные подсказкой типа.
Ранее, когда один документированный код Python, например, с Sphinx , некоторые из вышеперечисленных функций можно было получить, написав строки документов, отформатированные так:
def pick(l, index):
"""
:param l: list of integers
:type l: list
:param index: index at which to pick an integer from *l*
:type index: int
:returns: integer at *index* in *l*
:rtype: int
"""
return l[index]
Как видите, для этого требуется ряд дополнительных строк (точное число зависит от того, насколько явно вы хотите быть и как вы форматируете строку документации).Но теперь вам должно быть ясно, как PEP 3107 предоставляет альтернативу, которая во многих (всех?) Отношениях превосходна.Это особенно верно в сочетании с PEP 484 , который, как мы видели, предоставляет стандартный модуль, который определяет синтаксис для этих подсказок / аннотаций типов, который можно использовать таким образом, чтобы он был однозначным и точнымно гибкий, создавая мощную комбинацию.
По моему личному мнению, это одна из величайших возможностей Python за всю историю.Я не могу ждать, пока люди начнут использовать его силу.Извините за длинный ответ, но это то, что происходит, когда я волнуюсь.
Пример кода Python, который интенсивно использует подсказки типов, можно найти здесь .