funcdef: 'def' NAME parameters ['->' test] ':' suite
Необязательный блок 'arrow' отсутствовал в Python 2, и я не смог найти никакой информации о его значении в Python 3. Оказывается, это правильный Python, и он принят интерпретатором:
deff(x) -> 123: return x
Я думал, что это может быть какой-то синтаксис предварительного условия, но:
Я не могу протестировать x здесь, так как это все еще не определено,
Независимо от того, что я ставлю после стрелки (например, 2 < 1), это не влияет на поведение функции.
Может ли кто-нибудь, знакомый с этим синтаксическим стилем, объяснить это?
Более подробно, в Python 2.x есть docstrings , которые позволяют прикреплять строку метаданных к различным типам объектов. Это удивительно удобно, поэтому Python 3 расширяет эту функцию, позволяя вам присоединять метаданные к функциям, описывающим их параметры и возвращаемые значения.
Нет предвзятого варианта использования, но PEP предлагает несколько. Один из очень удобных способов - разрешить вам аннотировать параметры с их ожидаемыми типами; тогда было бы легко написать декоратор, который проверяет аннотации или приводит аргументы к нужному типу. Другой способ - разрешить документирование конкретных параметров вместо кодирования их в строку документации.
Ответ 2
Это аннотации функций, описанные в PEP 3107. В частности, -> обозначает аннотацию возвращаемой функции.
У вас также может быть структура данных python, а не просто строка:
rd={'type':float,'units':'Joules', 'docstring':'Given mass and velocity returns kinetic energy in Joules'} deff()->rd: pass
>>> f.__annotations__['return']['type'] <class'float'> >>> f.__annotations__['return']['units'] 'Joules' >>> f.__annotations__['return']['docstring'] 'Given mass and velocity returns kinetic energy in Joules'
Или вы можете использовать атрибуты функции для проверки вызываемых значений:
defvalidate(func, locals): for var, test in func.__annotations__.items(): value = locals[var] try: pr=test.__name__+': '+test.__docstring__ except AttributeError: pr=test.__name__ msg = '{}=={}; Test: {}'.format(var, value, pr) assert test(value), msg
defbetween(lo, hi): def_between(x): return lo <= x <= hi _between.__docstring__='must be between {} and {}'.format(lo,hi) return _between
>>> f(2,2) AssertionError: x==2; Test: _between: must be between 3and10 >>> f(3,2.1) AssertionError: y==2.1; Test: <lambda>
Ответ 3
В следующем коде:
deff(x) -> int: returnint(x)
-> int просто сообщает, что f() возвращает целое число (но это не заставляет функцию возвращать целое число). Это называется возвращаемой аннотацией, и к нему можно получить доступ как f.__annotations__['return'].
Python также поддерживает аннотации параметров:
deff(x: float) -> int: returnint(x)
: float сообщает людям, которые читают программу (и некоторые сторонние библиотеки / программы, например, pylint), что x должно быть float. Доступ к нему осуществляется как f.__annotations__['x'], и сам по себе он не имеет никакого значения. Смотрите документацию для получения дополнительной информации:
Как указывалось в других ответах, -> символ используется как часть аннотаций функций. Однако в более поздних версиях Python >= 3.5 он имеет определенное значение.
PEP 3107 -- Аннотации функций описывают спецификацию, определяя грамматические изменения, существование func.__annotations__, в котором они хранятся, и тот факт, что вариант их использования все еще открыт.
Самая быстрая из возможных схем - это ввести тихое устаревание аннотаций, не содержащих подсказок по типу, в 3.6, полное устаревание в 3.7 и объявить подсказки по типу как единственное разрешенное использование аннотаций в Python 3.8.
(Выделено мной)
На самом деле это не было реализовано на 3.6, насколько я могу судить, так что это может быть перенесено в будущие версии.
В соответствии с этим, приведенный вами пример:
deff(x) -> 123: return x
будет запрещено в будущем (и в текущих версиях будет сбивать с толку), его необходимо будет изменить на:
deff(x) -> int: return x
для эффективного описания этой функции f возвращает объект типа int.
Аннотации никоим образом не используются самим Python, он в значительной степени заполняет и игнорирует их. Работать с ними должны сторонние библиотеки.