[Python-3000] Questions on optional type annotations

Collin Winter collinw at gmail.com
Thu May 11 07:17:07 CEST 2006

I haven't been able to find any mention of these things in the
python-3000 archive (nor in Bill Birch's proto-PEP on the subject
[1]). These are all issues I've encountered while writing my typecheck
package [2], which I think still need to be discussed and addressed
for py3k's proposed type annotations.

1. Will there be some way of specifying "I expect parameter B to be a
callable with signature X"? If yes, how does this affect the
optional-ness of the type annotations?

Put another way: let's say I've annotated a function using the
following Haskell-derived strawman syntax. I want the sole parameter
to be a callable that accepts two ints and returns an int:

def foo((int, int -> int)): ...

What happens if I pass foo a function that doesn't have type
annotations, ie, a function where the system can't know its parameter
and return types (for example, functions from C extension modules)? Is
a TypeError raised (ie, you're forced to supply annotations)? Does the
system simply accept the function and trust you've done the right
thing? Is the function accepted but a warning is issued?

If a TypeError is raised, do we risk heading toward C's const
propagation issues?

2. On a related note, will there be a way to add annotations to
callables in extension modules?

3. Let's say you have two classes, each of which has methods that
return instances of the other class. How do you supply type
annotations for these? One has to be written above (and hence parsed
and compiled) before the other, meaning that without some way of
deferring the lookup of the type used in the annotation, you get
NameErrors (or the equivalent in this case).

typecheck solves this in an ugly way, using a Class() utility class to
delay the lookup. Roughly translated in to BDFL syntax:

class A:
   def foo(self, b_instance: B): ...

class B:
    def bar(self, a_instance: A): ...


class A:
   def foo(self, b_instance: Class('B')): ...

class B:
    def bar(self, a_instance: A): ...

The first time we need Class('B') for typechecking purposes, some
sys._getframe hackery is used to grab the real class instance and
cache it for later. (By the way, I'd love alternative suggestions
about how to do this in current Python.)

Bill mentions converting the name of the type/interface/whatever to
later-evaluated lambdas in the case of recursive datatypes, but I
don't see any mention of generalising this idea.

4. How will tuples be treated? Some in the wider Python community
treat tuples as simple frozen lists, while others view them as a data
structures unto themselves. My question: will (0,), (0, 1) and (0, 1,
2) all match (int,) (frozen list view), or are (int,), (int, int) and
(int, int, int) totally separate datatypes (more of a functional
programming view)?

Collin Winter

[1] - http://billbirch.wordpress.com/2006/05/01/draft-pep-types-for-python-3000/
[2] - http://oakwinter.com/code/typecheck/

More information about the Python-3000 mailing list