Вопрос-Ответ

What does -> mean in Python function definitions?

Что означает -> в определениях функций Python?

Недавно я заметил кое-что интересное при просмотре спецификации грамматики Python 3.3:

funcdef: 'def' NAME parameters ['->' test] ':' suite

Необязательный блок 'arrow' отсутствовал в Python 2, и я не смог найти никакой информации о его значении в Python 3. Оказывается, это правильный Python, и он принят интерпретатором:

def f(x) -> 123:
return x

Я думал, что это может быть какой-то синтаксис предварительного условия, но:


  • Я не могу протестировать x здесь, так как это все еще не определено,

  • Независимо от того, что я ставлю после стрелки (например, 2 < 1), это не влияет на поведение функции.

Может ли кто-нибудь, знакомый с этим синтаксическим стилем, объяснить это?

Переведено автоматически
Ответ 1

Это аннотация функции.

Более подробно, в Python 2.x есть docstrings , которые позволяют прикреплять строку метаданных к различным типам объектов. Это удивительно удобно, поэтому Python 3 расширяет эту функцию, позволяя вам присоединять метаданные к функциям, описывающим их параметры и возвращаемые значения.

Нет предвзятого варианта использования, но PEP предлагает несколько. Один из очень удобных способов - разрешить вам аннотировать параметры с их ожидаемыми типами; тогда было бы легко написать декоратор, который проверяет аннотации или приводит аргументы к нужному типу. Другой способ - разрешить документирование конкретных параметров вместо кодирования их в строку документации.

Ответ 2

Это аннотации функций, описанные в PEP 3107. В частности, -> обозначает аннотацию возвращаемой функции.

Примеры:

def kinetic_energy(m:'in KG', v:'in M/S')->'Joules': 
return 1/2*m*v**2

>>> kinetic_energy.__annotations__
{'return': 'Joules', 'v': 'in M/S', 'm': 'in KG'}

Аннотации - это словари, поэтому вы можете сделать это:

>>> '{:,} {}'.format(kinetic_energy(12,30),
kinetic_energy.__annotations__['return'])
'5,400.0 Joules'

У вас также может быть структура данных python, а не просто строка:

rd={'type':float,'units':'Joules',
'docstring':'Given mass and velocity returns kinetic energy in Joules'}
def f()->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'

Или вы можете использовать атрибуты функции для проверки вызываемых значений:

def validate(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

def between(lo, hi):
def _between(x):
return lo <= x <= hi
_between.__docstring__='must be between {} and {}'.format(lo,hi)
return _between

def f(x: between(3,10), y:lambda _y: isinstance(_y,int)):
validate(f, locals())
print(x,y)

С принтами

>>> f(2,2) 
AssertionError: x==2; Test: _between: must be between 3 and 10
>>> f(3,2.1)
AssertionError: y==2.1; Test: <lambda>
Ответ 3

В следующем коде:

def f(x) -> int:
return int(x)

-> int просто сообщает, что f() возвращает целое число (но это не заставляет функцию возвращать целое число). Это называется возвращаемой аннотацией, и к нему можно получить доступ как f.__annotations__['return'].

Python также поддерживает аннотации параметров:

def f(x: float) -> int:
return int(x)

: float сообщает людям, которые читают программу (и некоторые сторонние библиотеки / программы, например, pylint), что x должно быть float. Доступ к нему осуществляется как f.__annotations__['x'], и сам по себе он не имеет никакого значения. Смотрите документацию для получения дополнительной информации:

https://docs.python.org/3/reference/compound_stmts.html#function-definitions
https://www.python.org/dev/peps/pep-3107/

Ответ 4

Как указывалось в других ответах, -> символ используется как часть аннотаций функций. Однако в более поздних версиях Python >= 3.5 он имеет определенное значение.

PEP 3107 -- Аннотации функций описывают спецификацию, определяя грамматические изменения, существование func.__annotations__, в котором они хранятся, и тот факт, что вариант их использования все еще открыт.

В Python, 3.5 однако, PEP 484 -- Type Hints придает этому единственное значение: -> используется для указания типа, который возвращает функция. Также похоже, что это будет применяться в будущих версиях, как описано в Как насчет существующего использования аннотаций:


Самая быстрая из возможных схем - это ввести тихое устаревание аннотаций, не содержащих подсказок по типу, в 3.6, полное устаревание в 3.7 и объявить подсказки по типу как единственное разрешенное использование аннотаций в Python 3.8.


(Выделено мной)

На самом деле это не было реализовано на 3.6, насколько я могу судить, так что это может быть перенесено в будущие версии.

В соответствии с этим, приведенный вами пример:

def f(x) -> 123:
return x

будет запрещено в будущем (и в текущих версиях будет сбивать с толку), его необходимо будет изменить на:

def f(x) -> int:
return x

для эффективного описания этой функции f возвращает объект типа int.

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

python python-3.x