Другие ответы хорошо объяснили типизацию утки и простой ответ от 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 не будет поднимать a, 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
- когда это может быть Нет. Сокращение для 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, который интенсивно использует хинтинг типов, можно найти здесь .