Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does -> mean in Python function definitions?

I've recently noticed something interesting when looking at Python 3.3 grammar specification:

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

The optional 'arrow' block was absent in Python 2 and I couldn't find any information regarding its meaning in Python 3. It turns out this is correct Python and it's accepted by the interpreter:

def f(x) -> 123:     return x 

I thought that this might be some kind of a precondition syntax, but:

  • I cannot test x here, as it is still undefined,
  • No matter what I put after the arrow (e.g. 2 < 1), it doesn't affect the function behavior.

Could anyone familiar with this syntax style explain it?

like image 450
Krotton Avatar asked Jan 17 '13 13:01

Krotton


People also ask

What is -> symbol in Python?

This is function annotations. It can be use to attach additional information to the arguments or a return values of functions. It is a useful way to say how a function must be used.

What does -> None do in Python?

The None keyword is used to define a null value, or no value at all. None is not the same as 0, False, or an empty string. None is a data type of its own (NoneType) and only None can be None.

What does the arrow after a function mean in Python?

Straight as an arrow Python doesn't use arrow notation, like JavaScript — so what is this arrow doing? This, friend, is a return value annotation, which is part of function annotation, and it's a feature of Python 3 - and has been here since 3.0!


2 Answers

It's a function annotation.

In more detail, Python 2.x has docstrings, which allow you to attach a metadata string to various types of object. This is amazingly handy, so Python 3 extends the feature by allowing you to attach metadata to functions describing their parameters and return values.

There's no preconceived use case, but the PEP suggests several. One very handy one is to allow you to annotate parameters with their expected types; it would then be easy to write a decorator that verifies the annotations or coerces the arguments to the right type. Another is to allow parameter-specific documentation instead of encoding it into the docstring.

like image 129
Katriel Avatar answered Oct 15 '22 02:10

Katriel


These are function annotations covered in PEP 3107. Specifically, the -> marks the return function annotation.

Examples:

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'} 

Annotations are dictionaries, so you can do this:

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

You can also have a python data structure rather than just a string:

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' 

Or, you can use function attributes to validate called values:

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) 

Prints

>>> f(2,2)  AssertionError: x==2; Test: _between: must be between 3 and 10 >>> f(3,2.1) AssertionError: y==2.1; Test: <lambda> 
like image 39
dawg Avatar answered Oct 15 '22 01:10

dawg