[Python-ideas] Lessons from typing hinting Whoosh (PEP484)

Guido van Rossum guido at python.org
Mon Nov 16 17:32:42 EST 2015


On Mon, Nov 16, 2015 at 2:16 PM, Andrew Barnert <abarnert at yahoo.com> wrote:
> On Nov 16, 2015, at 09:31, Guido van Rossum <guido at python.org> wrote:
>>
>> If you really want DocId to be as small as int you should add
>> `__slots__ = ()` to the class def. It's still a bit slower (some code
>> special-cases exactly int) and it also has some other imperfections --
>> e.g. DocId(2) + DocId(2) == int(4), not DocId(4). But that's probably
>> okay for a document ID (and the solution is way too messy to use).
>
> Good points. But I don't think any of those things matter for the OP's use case.

Well, *you* claimed there was no size difference.

> And surely being able to runtime-check the type and get the same results as compile-time checks, and not requiring any new language features, are advantages?

Now you're changing the subject -- Matt very specifically asked for
something that at runtime was just an int but was tracked more
specifically by the type checker. We currently don't have that:
there's either some runtime overhead (your solution) or the type
checker doesn't track it (type aliasing as PEP 484 defines it).

Anyway, lots of things PEP 484 tracks cannot be checked at runtime
(e.g. anything involving TypeVar).

> I'm sure there are cases where the performance matters, but are there enough cases where the performance matters, runtime typing (e.g., in logs and debugger) doesn't matter, and static typing does matter?

A key requirement for PEP 484 is that there's no runtime overhead
(apart from modules loading a tiny bit slower because the annotations
are evaluated). Otherwise people will be afraid of using it. Having
zillions of subclasses of builtin types at runtime just so the type
checker can track them separately is in direct contradiction to this
requirement. (Note that the BDFL-delegate specifically insisted that
we remove isinstance() support from PEP-484's types.)

> As a side note, most of the C++ family have something akin to "typedef" and/or "using" type aliases that are explicitly _not_ treated as different types by the static typing algorithm: if your function wants a DocId and I pass an int, you get neither an error nor a warning, because they are literally just different names for the same type.

Yes, that's what PEP 484 type aliases do too.

> So, if Python really does need a feature that's stricter than what C++ and friends do, using a name that evokes comparisons to their feature is probably not a good idea. The way C++ does what the OP is asking for is exactly what I suggested: an empty class that publicly inherits the type. (Of course it only works with class types, not simple types like int, in C++. But Python only has class types, so that wouldn't be a problem.)

But C++ classes like that have no runtime overhead. The equivalent
Python syntax does, alas.

>> But in general this is a pretty verbose option.
>
> Even with __slots__, it's fewer characters, and the same number of concepts, as the OP's proposed solution.

But such a hack -- everytime someone sees that they'll wonder why the
`__slots__ = ()`. And AFAICT Matt didn't propose any solution -- he
just showed some example code indicating what he wanted to be taken
care of automatically.

> I think it's also more obvious to read: you're saying that DocId is a brand-new type that's a subtype of int (that adds nothing), which by definition means it can be used anywhere an int can be used, but not vice-versa. You don't have to know anything about MyPy or isinstance or anything else to figure out how they'll handle it (except the basic knowledge that Python's type system is generally a sensible OO system).

Yeah, but I'd still prefer a solution that is only read by the type
checker. And defining subclasses of int is pretty uncommon, so it'll
confuse the heck out of a lot of readers -- much more so than other
parts of type annotations (which are ignorable).

Anyway, let's stop bickering until Matt has had the time to read the
thread and respond.

-- 
--Guido van Rossum (python.org/~guido)


More information about the Python-ideas mailing list