Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What good are Python function annotations? [duplicate]

I have gone through the first couple of sections in PEP 3107, but I still don't get what good they do for the language. It seems to me that you can add metadata to functions using decorators. e.g.

def returns(return_type):   f.return_type = return_type  # <- adding metadata here   return f  @returns(Foo) def make_foo(): ... 

You can add metadata to arguments too, and it can look pretty if you take advantage of default arguments, like so:

import inspect  def defaults_are_actually_metadata(f):   names, args_name, kwargs_name, defaults = inspect.getfuncspec(f)   f.parameter_metadata = dict(zip(names[-len(defaults):], defaults))   f.__defaults__ = ()   return f  @defaults_are_actually_metadata def haul(load="Stuff to be carried.",          speed_mph="How fast to move the load (in miles per hour)."): ... 

At least my initial impression is that annotations are superfluous: decorators can do everything that annotations can (and more). Why are annotations better than decorators when it comes to adding metadata to functions?

like image 962
allyourcode Avatar asked Dec 09 '12 04:12

allyourcode


People also ask

What are good uses for Python function annotations?

The typeannotations module provides a set of tools for type checking and type inference of Python code. It also a provides a set of types useful for annotating functions and objects. These tools are mainly designed to be used by static analyzers such as linters, code completion libraries and IDEs.

What is __ annotations __ in Python?

__annotations__ Quirks __annotations__ the object will create a new empty dict that it will store and return as its annotations. Deleting the annotations on a function before it has lazily created its annotations dict will throw an AttributeError ; using del fn.

Should I use Python type annotations?

Type hints work best in modern Pythons. Annotations were introduced in Python 3.0, and it's possible to use type comments in Python 2.7. Still, improvements like variable annotations and postponed evaluation of type hints mean that you'll have a better experience doing type checks using Python 3.6 or even Python 3.7.

What advantage does using type annotations in function definitions provide?

It allows the developer to effectively communicate expected argument types and return values with the interpreter (and other developers as well) while keeping the advantages of dynamic typing.


2 Answers

As you mentioned, the relevant PEP is 3107 (linked for easy reference in case others encountering this question haven't read it yet).

For now, annotations are kind of an experiment, and kind of a work in progress. There is actually a recent thread in the python-ideas mailing list on the topic which may be helpful. (The link provided is just for the monthly archive; I find that the URL for specific posts tends to change periodically. The thread in question is near the beginning of December, and titled "[Python-ideas] Conventions for function annotations". The first post is from Thomas Kluyver on Dec 1.)

Here's a bit from one of Guido van Rossum's posts in that thread:

On 12/4/2012 11:43 AM, Jasper St. Pierre wrote:

Indeed. I've looked at annotations before, but I never understood the purpose. It seemed like a feature that was designed and implemented without some goal in mind, and where the community was supposed to discover the goal themselves.

Guido's response:

To the contrary. There were too many use cases that immediately looked important, and we couldn't figure out which ones would be the most important or how to combine them, so we decided to take a two-step approach: in step 1, we designed the syntax, whereas in step 2, we would design the semantics. The idea was very clear that once the syntax was settled people would be free to experiment with different semantics -- just not in the stdlib. The idea was also that eventually, from all those experiments, one would emerge that would be fit for the stdlib.

Jasper St. Pierre:

So, if I may ask, what was the original goal of annotations? The PEP gives some suggestions, but doesn't leave anything concrete. Was it designed to be an aid to IDEs, or static analysis tools that inspect source code? Something for applications themselves to munge through to provide special behaviors, like a command line parser, or runtime static checker?

Guido's response:

Pretty much all of the above to some extent. But for me personally, the main goal was always to arrive at a notation to specify type constraints (and maybe other constraints) for arguments and return values. I've toyed at various times with specific ways of combining types. E.g. list[int] might mean a list of integers, and dict[str, tuple[float, float, float, bool]] might mean a dict mapping strings to tuples of three floats and a bool. But I felt it was much harder to get consensus about such a notation than about the syntax for argument annotations (think about how many objections you can bring in to these two examples :-) -- I've always had a strong desire to use "var: type = default" and to make the type a runtime expression to be evaluated at the same time as the default.

And a tiny bit of humor from Ned Batchelder:

A telling moment for me was during an early Py3k keynote at PyCon (perhaps it was in Dallas or Chicago?), Guido couldn't remember the word "annotation," and said, "you know, those things that aren't type declarations?" :-)

like image 185
John Y Avatar answered Sep 22 '22 23:09

John Y


I think that the first paragraph states it all:

Because Python's 2.x series lacks a standard way of annotating a function's parameters and return values

(emphasis mine)

Having a standard way to do this has the advantage that you know exactly where the annotations will be located.

As for your argument about there's another way to do it, you could make the same argument against list comprehensions:

out = [] for x in my_iterable:     out.append(x) 
like image 31
mgilson Avatar answered Sep 19 '22 23:09

mgilson