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



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



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


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



def f(x) -> 123:
return x


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




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

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


может ли кто-нибудь, привыкший к этому синтаксису, объяснить это?

638   3  

3 ответов:

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

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

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

это аннотации функций, описанные в 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(20,3000),
      kinetic_energy.__annotations__['return'])
'90,000,000.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>

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

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

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

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

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

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

согласно этому, пример, который вы предоставили:

def f(x) -> 123:
    return x

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

def f(x) -> int:
    return x

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

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

Comments

    Ничего не найдено.