[Python-ideas] PEP 484 (Type Hints) -- first draft round

Steven D'Aprano steve at pearwood.info
Mon Jan 19 02:58:39 CET 2015

On Sun, Jan 18, 2015 at 05:24:51PM -0500, Cem Karan wrote:

> def foo(a: {Type(int), Doc("some doc")}, b):
>     pass

I dislike this, because there is too much in the function signature. I 
could live with this:

def foo(a:int, b): pass

or *possibly* this:

def foo(a:"some doc", b): pass

but not both together. Combining the two doesn't look too bad for a toy 
example like made-up "foo", but think about a real-world example:

# from the statistics module
def median_grouped(
        data: {Type(Iterable[Real]), Doc("grouped continuous data")},
        interval: {Type(Real), Doc("class interval")} = 1
        ) -> {Type(Real), Doc(
              "50th percentile (median) of grouped continuous data")}:

That may be machine-readable, but it is too complicated for me to read, 
and I wrote it! And that's only a simple function with a mere two 
parameters and simple one-liner docs.

Having written that, I still need to write a doc string, and almost 
certainly I have to duplicate the annotation docs inside the docstring. 
So it isn't really saving me much, if anything, over this:

@Doc({"data": "grouped continuous data",
      "interval": "class interval",
      "return": "50th percentile (median) of grouped continuous data"
def median_grouped(data:Iterable[Real], interval:Type(Real)=1)->Real:

It's not *ideal* to have to duplicate the parameter names in the 
decorator, but except in the most trivial toy cases, I can't have it 

- type annotations
- and document annotations
- without being too verbose or complex
- and still easy to read and write and maintain

Something has to give, and since type-hinting is deemed to be the 
primary use for annotations, it has to be the document annotations. You 
can still have both type-hints and docs, you just can't use annotations 
for them both. (But see below.)

- If you want to use annotations for documentation, then you 
  cannot use them for type-hints at the same time;
- if you want to use annotations for type-hints, then you
  need another method of dealing with the documentation.

Since you almost certainly will need to write a docstring anyway, the 
best solution in my mind is to move the documentation into the 

def median_grouped(data:Iterable[Real], interval:Type(Real)=1)->Real:
    """Return the 50th percentile (median) of grouped continuous data.

    :param a: grouped continuous data
    :param interval: class interval

    more documentation and docstrings follows...

> With annotations, the documentation lives with the argument.  If 
> typing rules all, then you might accidentally have the following:
> def foo(a: int, b):
>     """
>     :param a: some doc
>     :type a: str <- Whoops!  Type conflict!
>     """
>     pass

And that is best solved by having your linter understand the convention 
for docstrings and flag the error.

> I'm arguing that with annotations we can put a lot more information in 
> about a given function argument/return value than just typing.

Of course you can. But I think you shouldn't.

You are absolutely free to disagree. Remember, use of the type-checker 
is optional, and the type-checker itself will be a third-party tool. 
Tools actually. I expect there will be much competition to develop the 
best, most powerful type-checker.

There is nothing stopping people (including yourself) writing a 
type-checker which supports your multiple-annotations-in-a-set idea. If 
it proves itself as a viable, and popular, alternative, then you can 
come back and try to convince Guido to give it his blessing as 
officially sanctioned (at which point all the other type-checkers will 
have to support sets of annotations as well).

I *do* believe that it is technically possible to have the type-checker 
support your {Type(...), Spam(...)} idea, but I *don't* believe that it 
will be practical or popular. I think it is a case of YAGNI combined 
with EIYDNIYSDI (Even If You Do Need It You Shouldn't Do It). But I 
might be wrong, and I encourage you to prove me wrong the only way that 
really matters: with working code that gets used in the real world.


More information about the Python-ideas mailing list