Если я не ошибаюсь, создание функции в Python работает так:
def my_func(param1, param2):
# stuff
Однако вы на самом деле не указываете типы этих параметров. Кроме того, если я помню, Python является строго типизированным языком, поэтому кажется, что Python не должен позволять вам передавать параметр другого типа, чем ожидал создатель функции. Однако как Python узнает, что пользователь функции передает правильные типы? Будет ли программа просто умирать, если это неправильный тип, предполагая, что функция действительно использует параметр? Вы должны указать тип?
python
function
parameters
Лейф Андерсен
источник
источник
Ответы:
Python строго типизирован, потому что каждый объект имеет тип, каждый объект знает его тип, невозможно случайно или преднамеренно использовать объект типа «как если бы» это был объект другого типа, и все элементарные операции над объектом делегирован по своему типу.
Это не имеет ничего общего с именами . Имя в Python не «имеют тип»: если и когда это определено имя, название относится к объекту , а объект имеет тип (но это не на самом деле силы типа на имя : A имя есть имя).
Имя в Python может превосходно ссылаться на разные объекты в разное время (как в большинстве языков программирования, хотя и не на всех) - и нет никаких ограничений на имя, так что, если оно когда-то ссылалось на объект типа X, тогда он навсегда ограничен ссылками только на другие объекты типа X. Ограничения на имена не являются частью концепции «строгой типизации», хотя некоторые энтузиасты статической типизации (где имена действительно ограничены, и в статической компиляции AKA время, мода тоже) не употребляйте термин таким образом.
источник
try
/except
) Произойдет, когда и если будет предпринята попытка выполнить операцию, которую объект не поддерживает. В Python 3.5 теперь вы можете по желанию «указать типы» аргументов, но, по сути, ошибки не возникает, если спецификация нарушена; нотация ввода предназначена только для того, чтобы помочь отдельным инструментам, которые выполняют анализ и т. д., она не изменяет поведение самого PythonДругие ответы хорошо объяснили типизацию утки и простой ответ от tzot :
Однако одна интересная вещь изменилась с 2010 года (когда вопрос был задан впервые), а именно реализация PEP 3107 (реализована в Python 3). Теперь вы можете указать тип параметра и тип возвращаемого типа функции, например:
Здесь мы видим, что
pick
принимает 2 параметра, списокl
и целое числоindex
. Также должно возвращаться целое число.Таким образом, здесь подразумевается, что
l
это список целых чисел, который мы можем увидеть без особых усилий, но для более сложных функций это может немного сбить с толку относительно того, что этот список должен содержать. Мы также хотим, чтобы значение по умолчаниюindex
было равно 0. Чтобы решить эту проблему, вы можете написатьpick
так:Обратите внимание, что теперь мы помещаем строку как тип
l
, который синтаксически разрешен, но он не подходит для программного анализа (к которому мы вернемся позже).Важно отметить, что Python не будет поднимать a,
TypeError
если вы передадите поплавокindex
, причина этого - один из основных моментов в философии дизайна Python: «Мы все здесь взрослые по обоюдному согласию» , что означает, что вы должны знать, что вы можете передать функции, а что нет. Если вы действительно хотите написать код, который выдает TypeErrors, вы можете использоватьisinstance
функцию, чтобы проверить, что переданный аргумент имеет правильный тип или его подкласс, например:Подробнее о том, почему вы должны делать это редко, и о том, что вы должны делать вместо этого, говорится в следующем разделе и в комментариях.
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
- используется в основном для функций, но может использоваться для других функций.Это наиболее распространенные типовые подсказки. Полный список можно найти в документации для модуля ввода .
Вот старый пример с использованием методов аннотации, введенных в модуле ввода:
Одной из мощных функций является
Callable
возможность ввода аннотированных методов, которые принимают функцию в качестве аргумента. Например:Приведенный выше пример может стать более точным с использованием
TypeVar
вместоAny
, но это было оставлено читателю как упражнение, так как я считаю, что я уже наполнил свой ответ слишком большим количеством информации о замечательных новых функциях, включаемых хинтингом типов.Ранее, когда один документированный код Python с, например, Sphinx, некоторые из вышеперечисленных функциональных возможностей можно было получить, написав строки документов в следующем формате:
Как видите, для этого требуется ряд дополнительных строк (точное число зависит от того, насколько явно вы хотите быть и как вы форматируете строку документации). Но теперь вам должно быть ясно, как PEP 3107 предоставляет альтернативу, которая во многих (всех?) Отношениях лучше. Это особенно верно в сочетании с PEP 484, который, как мы видели, предоставляет стандартный модуль, определяющий синтаксис для этих подсказок / аннотаций типов, который можно использовать таким образом, чтобы он был однозначным и точным, но при этом гибким, что мощная комбинация.
По моему личному мнению, это одна из величайших возможностей Python. Я не могу ждать, пока люди начнут использовать его силу. Извините за длинный ответ, но это то, что происходит, когда я волнуюсь.
Пример кода Python, который интенсивно использует хинтинг типов, можно найти здесь .
источник
TypeError
, какой смысл использовать определение вpick(l: list, index: int) -> int
виде одной строки? Или я неправильно понял, я не знаю.__annotations__
атрибуте объекта функции).def f(a) -> Tuple[int, int]:
Вы не указываете тип. Метод завершится ошибкой (во время выполнения), только если попытается получить доступ к атрибутам, которые не определены в передаваемых параметрах.
Итак, эта простая функция:
... не потерпит неудачу независимо от того, какие два аргумента передаются.
Однако эта функция:
... потерпит неудачу во время выполнения, если
param1
иparam2
оба не имеют именуемых атрибутовquack
.источник
Многие языки имеют переменные, которые имеют определенный тип и имеют значение. Python не имеет переменных; у него есть объекты, и вы используете имена для ссылки на эти объекты.
На других языках, когда вы говорите:
затем переменная (обычно целочисленная) меняет свое содержимое на значение 1.
В Python
означает «использовать имя a для обозначения объекта 1 ». Вы можете сделать следующее в интерактивном сеансе Python:
Функция
type
вызывается с объектом1
; Поскольку каждый объект знает свой тип, его легкоtype
найти и вернуть.Аналогично, всякий раз, когда вы определяете функцию
функция получает два объекта и называет их
param1
иparam2
независимо от их типов. Если вы хотите убедиться, что полученные объекты относятся к определенному типу, закодируйте свою функцию так, как если бы они были нужного типа (типов), и перехватите исключения, которые выдают, если это не так. ОбычноTypeError
генерируются исключения (вы использовали недопустимую операцию) иAttributeError
(вы пытались получить доступ к несуществующему члену (методы тоже являются членами)).источник
Python не является строго типизированным в смысле статической проверки или проверки типов во время компиляции.
Большая часть кода Python подпадает под так называемую «Duck Typing» - например, вы ищете метод
read
для объекта - вам все равно, является ли объект файлом на диске или сокетом, вы просто хотите прочитать N байтов из него.источник
Как объясняет Алекс Мартелли ,
Прочитайте остальную часть его поста для полезной информации.
источник
Python не заботится о том, что вы передаете его функциям. При вызове
my_func(a,b)
переменные param1 и param2 будут содержать значения a и b. Python не знает, что вы вызываете функцию с правильными типами, и ожидает, что программист позаботится об этом. Если ваша функция будет вызываться с различными типами параметров, вы можете обернуть код, обращаясь к ним, с помощью блоков try / кроме и оценить параметры любым удобным для вас способом.источник
Вы никогда не указываете тип; Python имеет концепцию типизации утки ; в основном код, который обрабатывает параметры, делает определенные предположения о них - возможно, вызывая определенные методы, которые предполагается реализовать параметром. Если параметр имеет неправильный тип, то будет сгенерировано исключение.
В целом, ваш код должен гарантировать, что вы передаете объекты нужного типа - нет компилятора, который обеспечивал бы это заранее.
источник
Есть одно печально известное исключение из печати утки, о которой стоит упомянуть на этой странице.
Когда
str
функция вызывает__str__
метод класса, она тонко проверяет свой тип:Как будто Гвидо намекает нам, какое исключение должно вызвать программа, если она встречает неожиданный тип.
источник
В Python все имеет тип. Функция Python будет делать все, что от нее требуется, если тип аргументов это поддерживает.
Пример:
foo
добавит все, что можно__add__
отредактировать;), не беспокоясь о его типе. Это означает, что во избежание неудачи вы должны предоставлять только те вещи, которые поддерживают сложение.источник
Я не видел, чтобы это упоминалось в других ответах, поэтому я добавлю это в банк.
Как уже говорили другие, Python не устанавливает тип для параметров функции или метода. Предполагается, что вы знаете, что делаете, и что если вам действительно нужно знать тип чего-то, что было передано, вы проверите это и решите, что делать для себя.
Одним из основных инструментов для этого является функция isinstance ().
Например, если я напишу метод, который ожидает получить необработанные двоичные текстовые данные, а не обычные строки в кодировке utf-8, я могу проверить тип параметров на входе и либо адаптироваться к тому, что я найду, либо вызвать исключение, чтобы отказаться.
Python также предоставляет все виды инструментов для копания в объектах. Если вы храбры, вы можете даже использовать importlib для создания ваших собственных объектов произвольных классов на лету. Я сделал это, чтобы воссоздать объекты из данных JSON. Такая вещь была бы кошмаром на статическом языке, таком как C ++.
источник
Чтобы эффективно использовать модуль ввода (новый в Python 3.5), включите все (
*
).И вы будете готовы к использованию:
Тем не менее, по- прежнему можно использовать имена типов , как
int
,list
,dict
, ...источник
Я реализовал оболочку, если кто-то хотел бы указать типы переменных.
Используйте это как:
РЕДАКТИРОВАТЬ
Приведенный выше код не работает, если не объявлен тип аргументов (или возвращаемых). Следующее редактирование может помочь, с другой стороны, оно работает только для kwargs и не проверяет args.
источник