[Types-sig] Sample declarations
Guido van Rossum
guido@digicool.com
Tue, 13 Mar 2001 09:52:10 -0500
> Here are some sample declarations from an experimental typecheck module.
> I'd like feedback because there are lots of subtle issues.
I think you're on a slippery slope with some assumptions about numeric
types here:
- Your test for number assumes that something can be converted to
complex. That may not be true.
- Your test for Integer includes float/complex numbers with integral
values; that doesn't work, e.g. a[1.0] raises TypeError if a is a
sequence.
- Your test for Float values that accepts ints is also bad news, at
least until integer division is fixed. You may want to define a
separate type IntOrFloat, for those cases where the programmer
asserts that either type is fine, and another IntOrFloatOrComplex.
> def findInterface(iface, obj):
> ifaces = getattr(obj, "__interfaces__", None)
> # don't make this mutually recursive on
> # Sequence.__implementedby__!
> if type(ifaces) in (types.ListType, types.TupleType):
> return iface in ifaces # multiple interfaces case
> else:
> return iface is ifaces # single interface case
This helper function is steeped in irrelevant implementation detail!
- Your assumptions about sequences, mappings etc. are also pretty
naive. operator.isSequenceType() and .isMappingType() return true
for all class instances regardless of what they actually implement,
and should this be avoided.
- One way to go would be to have explicit ways to say "x is any
Sequence", "x is a List", "x is any Mapping", "x is a Dictionary".
- But note again that Sequence-ness and Mapping-ness are ill-defined.
Look at this:
def C:
def __getitem__(self, x): return x
x = C()
Is x a sequence? A mapping? It could fake being either! Before
you can meaningfully discuss the Sequence check code, you should
make up your mind when you start calling something a sequence.
Clearly it needs __getitem__ (let's limit ourselves to class
instances). Does it need __len__? Does it need __getslice__? Does
it need to have count() and index()? reverse() and sort()? You
also need a separate type to indicate a writable sequence. For
mappings, there's a whole slew of methods that are informally part
of the mapping protocol yet aren't implemented by all mappings,
e.g. has_key(), keys(), values(), items(), get(), copy(), and for
mutable mappings, clear(), setdefault(), update().
- Similar questions can be asked about streams.
In short, it looks (and I am as surprised as you are!!!) like we will
need to agree on the Python type hierarchy before we can ever hope to
agree on any kind of type assertions. That is, unless you make the
type assertions only deal with the concrete types. But that wouldn't
be very useful, as there are lots of cases where you want to express
that you accept any kind of sequence, mapping, file, etc.
--Guido van Rossum (home page: http://www.python.org/~guido/)