[Python-ideas] Structural type checking for PEP 484

Sven R. Kunze srkunze at mail.de
Fri Sep 18 19:35:17 CEST 2015

On 18.09.2015 05:00, Steven D'Aprano wrote:
> I don't think they are all or nothing. I think it is possible to have
> incomplete documentation and partial test coverage -- it isn't like you
> go from "no documentation at all and zero tests" to "fully documented
> and 100% test coverage" in a single step.

This was a misunderstanding. The "all or nothing" wasn't about "test 
everything or don't do it at all". It was about the robustness of future 
benefits you gain from it. Either you have a test or you don't.

With type annotations you have 40% or 60% *depending* on the quality of 
the tool you use. It's fuzzy. I don't like to build stuff on jello. Just 
my personal feeling here.

> That's one use-case for them. Another use-case is as documentation:
> def agm(x:float, y:float)->float:
>      """Return the arithmetic-geometric mean of x and y."""
> versus
> def agm(x, y):
>      """Return the arithmetic-geometric mean of x and y.
>      Args:
>          x (float): A number.
>          y (float): A number.
>      Returns:
>          float: The agm of the two numbers.
>      """

The type annotation explains nothing. The short doc-string 
"arithmetic-geometric mean" explains everything (or prepare you to 
google it). So, I would prefer this one:

def agm(x, y):
     """Return the arithmetic-geometric mean of x and y."""

>> So, I have difficulties to
>> infer which parameters actually would benefit from annotating.
> The simplest process may be something like this:
> - run the type-checker in a mode where it warns about variables
>    with unknown types;
> - add just enough annotations so that the warnings go away.
> This is, in part, a matter of the quality of your tools. A good type
> checker should be able to tell you where it can, or can't, infer a type.

You see? Depending on who runs which tools, type annotations need to be 
added which are redundant for one tool and not for another and vice 
versa. (Yes, we allow that because we grant the liberty to our devs to 
use the tools they perform best with.)

Coverage, on the other hand, is strict. Either you traverse that line of 
code or you don't (assuming no bugs in the coverage tools).

>> I am
>> either doing redundant work (because the typechecker is already very
>> well aware of the type) or I actually insert explicit knowledge (which
>> might become redundant in case typecheckers actually become better).
> You make it sound like, alone out of everything else in Python
> programming, once a type annotation is added to a function it is carved
> in stone forever, never to be removed or changed :-)

Let me reformulate my point: it's not about setting things in stone. 
It's about having more to read/process mentally. You might think, 'nah, 
he's exaggerating; it's just one tiny little ": int" more here and 
there', but these things build up slowly over time, due to missing clear 
guidelines (see the fuzziness I described above). Devs will simply add 
them just everywhere just to make sure OR ignore the whole concept 

It's simply not good enough. :(

Nevertheless, I like the protocol idea more as it introduces actual 
names to be exposed by IDEs without any work from the devs. That's great!

You might further think, 'you're so lazy, Sven. First, you don't want to 
help the type checker but you still want to use it?' Yes, I am lazy! And 
I already benefit from it when using PyCharm. It might not be perfect 
but it still amazes me again and again what it can infer without any 
type annotations present.

> def spam(n=3):
>      return "spam"*n
> A decent type-checker should be able to infer that n is an int. What if
> you add a type annotation?
> def spam(n:int=3):
>      return "spam"*n

It's nothing seriously wrong with it (except what I described above). 
However, these examples (this one in particular) are/should not be 
real-world code. The function name is not helpful, the parameter name is 
not helpful, the functionality is a toy.

My observation so far:

1) Type checking illustrates its point well when using academic 
examples, such as the tuples-of-tuples-of-tuples-of-ints I described 
somewhere else on this thread or unreasonably short toy examples.

(This might be domain specific; I can witness it for business 
applications and web applications none of which actually need to solve 
hard problems admittedly.)

2) Just using constant and sane types like a class, lists of 
single-class instances and dicts of single-class instances for a single 
variable enables you to assign a proper name to it and forces you to 
design a reasonable architecture of your functionality by keeping the 
level of nesting at 0 or 1 and split out pieces into separate code blocks.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150918/13cafd29/attachment-0001.html>

More information about the Python-ideas mailing list