Типы параметров функции в Python

Если я не ошибаюсь, создание функции в Python работает следующим образом:

def my_func(param1, param2): # stuff 

Однако вы не даете типы этих параметров. Кроме того, если я помню, Python – строго типизированный язык, как таковой, похоже, что Python не должен пропускать параметр другого типа, чем ожидал создатель функции. Однако, как Python знает, что пользователь функции передает правильные типы? Будет ли программа просто умирать, если это неправильный тип, если функция действительно использует параметр? Вам нужно указать тип?

  • Как предотвратить использование urllib (2) Python из-за перенаправления
  • PyQt - Как угасить фон рабочего стола за диалогом (аналогично Windows UAC)?
  • Python: работа с cygwin работает, при запуске из PyCharm
  • Как правильно писать перекрестные ссылки на внешнюю документацию с помощью intersphinx?
  • Тип Hinting для объектов типа, который определяется
  • Как печать объекта приводит к другому результату, чем как str (), так и repr ()?
  • Не удается установить Pandas с OpenShift
  • i-й элемент k-й перестановки
  • 12 Solutions collect form web for “Типы параметров функции в Python”

    Python строго типизирован, потому что каждый объект имеет тип, каждый объект знает его тип, невозможно случайно или намеренно использовать объект типа «как бы», это был объект другого типа, и все элементарные операции над объектом делегированы его типу.

    Это не имеет ничего общего с именами . Имя в Python не имеет «тип»: если и когда определено имя, имя относится к объекту , и объект имеет тип (но это на самом деле не приводит к типу имени : a имя – это имя).

    Имя в Python может отлично ссылаться на разные объекты в разное время (как на большинстве языков программирования, хотя и не на всех) – и нет ограничения на такое имя, что если он когда-то ссылался на объект типа X, это навсегда ограничивается ссылкой только на другие объекты типа X. Ограничения на имена не являются частью концепции «сильной типизации», хотя некоторые энтузиасты статической типизации (где имена становятся ограниченными, а в статическом компиляторе AKA – время, мода тоже) неправильно используют термин этот путь.

    Другие ответы проделали хорошую работу по объяснению утиной печати и простому ответу 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 такой pick :

     def pick(l: "list of ints", index: int = 0) -> int: return l[index] 

    Обратите внимание, что теперь мы помещаем строку как тип l , которая синтаксически разрешена, но не подходит для разбора программно (о чем мы вернемся позже).

    Важно отметить, что Python не поднимет TypeError если вы передадите float в 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 , но это было оставлено как упражнение для читателя, так как я полагаю, что я уже заполнил свой ответ слишком большой информацией о замечательных новых функциях, включенных с помощью типа hinting ,


    Раньше, когда один документированный код Python с, например, Sphinx, некоторые из вышеперечисленных функций могли быть получены путем записи docstrings, отформатированных следующим образом:

     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, который сильно использует подсказку типа, можно найти здесь .

    Вы не указываете тип. Метод будет терпеть неудачу (во время выполнения), если он попытается получить доступ к атрибутам, которые не определены в параметрах, которые передаются.

    Итак, эта простая функция:

     def no_op(param1, param2): pass 

    … не сработает, независимо от того, что передают два аргумента.

    Однако эта функция:

     def call_quack(param1, param2): param1.quack() param2.quack() 

    … будет работать во время выполнения, если параметры param1 и param2 не имеют атрибутов, называемых quack .

    Python не строго типизирован в смысле статической или компиляции времени.

    Большинство Python-кода попадают под так называемый «Duck Typing» – например, вы ищете метод, read на объекте, – вам все равно, является ли объект файлом на диске или сокете, вы просто хотите прочитать N байтов.

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

    На других языках, когда вы говорите:

     a = 1 

    то переменная (обычно целочисленная) меняет свое содержимое на значение 1.

    В Python,

     a = 1 

    означает «использовать имя a для обозначения объекта 1 ». Вы можете сделать следующее в интерактивной сессии Python:

     >>> type(1) <type 'int'> 

    Тип функции вызывается с объектом 1 ; так как каждый объект знает свой тип, легко найти тип указанного типа и вернуть его.

    Аналогично, всякий раз, когда вы определяете функцию

     def funcname(param1, param2): 

    функция получает два объекта и называет их param1 и param2 независимо от их типов. Если вы хотите удостовериться, что полученные объекты относятся к определенному типу, введите свою функцию так, как будто они имеют нужный тип (ы) и поймают исключения, которые выбрасываются, если они не являются. Исключенные исключения обычно являются TypeError (вы использовали недопустимую операцию) и AttributeError (вы пытались получить доступ к несуществующему члену (методы тоже являются членами)).

    Как объясняет Алекс Мартелли ,

    Обычное, Pythonic, предпочтительное решение почти неизменно «утиная печать»: попробуйте использовать аргумент, как если бы он был определенного типа, сделайте это в инструкции try / except, захватывая все исключения, которые могут возникнуть, если аргумент не был фактически этого типа (или любого другого типа, красиво утка-имитирующего его ;-), а в предложении except попробуйте что-то еще (используя аргумент «как будто« это был какой-то другой тип »).

    Прочитайте остальную часть своего сообщения за полезную информацию.

    Python не заботится о том, что вы передаете своим функциям. Когда вы вызываете my_func(a,b) , переменные param1 и param2 будут удерживать значения a и b. Python не знает, что вы вызываете функцию с соответствующими типами, и ожидает, что программист позаботится об этом. Если ваша функция будет вызываться с различными типами параметров, вы можете обернуть код, обращаясь к ним с помощью блоков try / except и оценить параметры любым способом.

    Вы никогда не укажете тип; Python имеет концепцию утиной печати ; в основном код, обрабатывающий параметры, будет делать определенные предположения о них – возможно, путем вызова определенных методов, которые ожидается реализовать параметром. Если параметр имеет неправильный тип, тогда будет выбрано исключение.

    В общем, это зависит от вашего кода, чтобы убедиться, что вы проходите вокруг объектов соответствующего типа – компилятор не должен применять это раньше времени.

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

    Когда str функция вызывает метод класса __str__ она тонко выводит его тип:

     >>> class A(object): ... def __str__(self): ... return 'a','b' ... >>> a = A() >>> print a.__str__() ('a', 'b') >>> print str(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __str__ returned non-string (type tuple) 

    Как будто Guido намекает на то, какое исключение должно было бы повысить для программы, если она встречает неожиданный тип.

    В python все имеет тип. Функция Python будет делать все, что просят сделать, если тип аргументов ее поддерживает.

    Пример: foo добавит все, что может быть __add__ ed;), не беспокоясь о его типе. Таким образом, чтобы избежать сбоя, вы должны предоставлять только те вещи, которые поддерживают добавление.

     def foo(a,b): return a + b class Bar(object): pass class Zoo(object): def __add__(self,other): return 'zoom' if __name__=='__main__': print foo(1,2) print foo('james','bond') print foo(Zoo(),Zoo()) print foo(Bar(),Bar()) # should fail 

    Я не видел этого в других ответах, поэтому я добавлю это в банк. Как говорили другие, python не применяет тип функции или параметры метода. Предполагается, что вы знаете, что делаете, и если вам действительно нужно знать тип чего-то, что было передано, вы проверите его и решите, что делать для себя.

    Одним из основных инструментов для этого является функция isinstance ().

    Например, если я напишу метод, который ожидает получить необработанные двоичные текстовые данные, а не обычные строки с кодировкой utf-8, я мог бы проверить тип параметров на пути и либо адаптироваться к тому, что я нахожу, либо поднять исключение для отказа.

     def process(data): if not isinstance(data, bytes) and not isinstance(data, bytearray): raise TypeError('Invalid type: data must be a byte string or bytearray, not %r' % type(data)) # do more stuff 

    Python также предоставляет всевозможные инструменты для поиска объектов. Если вы храбры, вы можете даже использовать importlib для создания собственных объектов произвольных классов, на лету. Я сделал это, чтобы воссоздать объекты из данных JSON. Такое было бы кошмаром на статичном языке, таком как C ++.

    Вы можете вызвать функцию, используя следующие типы формальных аргументов

    1. Обязательный аргумент: Обязательные аргументы – это аргументы, переданные функции в правильном позиционном порядке. Здесь количество аргументов в вызове функции должно точно совпадать с определением функции.

    2. Аргумент ключевого слова. Аргументы ключевого слова связаны с вызовом функции. Когда вы используете аргументы ключевого слова в вызове функции, вызывающий идентифицирует аргументы по имени параметра. Это позволяет вам пропускать аргументы или размещать их вне порядка, потому что интерпретатор Python может использовать ключевые слова, предоставленные для соответствия значениям с параметрами.

    3. Аргумент аргумента по умолчанию: аргумент по умолчанию – это аргумент, который принимает значение по умолчанию, если значение не указано в вызове функции для этого аргумента.

    4. Variable – Length Argument: вам может потребоваться обработать функцию для большего количества аргументов, которые вы указали при определении функции. Эти аргументы называются «аргументы переменной длины» и не называются в определении функции, в отличие от обязательных и стандартных аргументов.

    Python - лучший язык программирования в мире.