Live data from Hacker News

A Failed Experiment with Python Type Annotations

mortoray.com

11–20 of 82 posts

Re: A Failed Experiment with Python Type Annotations

#11

Why would you keep Python if you want static typing? I mean, there are several modern, performant (more than Python actually) statically typed languages. Rust, Go, Kotlin, Scala, Swift… All of them are mature and have a good library ecosystem. So, except if you need some math/AI/ML packages available only for Python, why bother? Choose the right tool for the job, no?

> Seems like all of this (adding static typing on top of Python, PHP, etc) started with the success of TypeScript Mypy is a few years older than TypeScript, so, no.

Yep, already removed that part since I was not sure about the historic and it actually doesn't matter who started the trend.

Re: A Failed Experiment with Python Type Annotations

#12

> mypy has no trouble understanding this, but it’s unfortunately not valid Python code. You can’t refer to Node within the Node class. No, the workaround is to stringify "Node". class Node(Object): def add_sub(self, sub: 'Node'): ... def get_subs(self) -> Sequence['Node']: #Or maybe 'Sequence[Node]' works just fine. As of python3.7, this stringification is done by automatically under a from future import, and will ev…

> But you should still annotate your public apis.

The good thing about inference (especially with a REPL) is you can write it without the annotation, and then use the inferred type (in Haskell, I usually find that when I resist the temptation to explicitly annotate types, the actual types are more general than I would have specified.)

Re: A Failed Experiment with Python Type Annotations

#13

Why would you keep Python if you want static typing? I mean, there are several modern, performant (more than Python actually) statically typed languages. Rust, Go, Kotlin, Scala, Swift… All of them are mature and have a good library ecosystem. So, except if you need some math/AI/ML packages available only for Python, why bother? Choose the right tool for the job, no?

> Choose the right tool for the job, no?

The thing is, static typing is never the job by itself.

Re: A Failed Experiment with Python Type Annotations

#14

> mypy has no trouble understanding this, but it’s unfortunately not valid Python code. You can’t refer to Node within the Node class. No, the workaround is to stringify "Node". class Node(Object): def add_sub(self, sub: 'Node'): ... def get_subs(self) -> Sequence['Node']: #Or maybe 'Sequence[Node]' works just fine. As of python3.7, this stringification is done by automatically under a from future import, and will ev…

As well as pytype, you can use a separate tool to discover the correct annotations, then verify them and add them to your source code. There are a couple - MonkeyType, pyannotate and pytypes.

Re: A Failed Experiment with Python Type Annotations

#15

> mypy has no trouble understanding this, but it’s unfortunately not valid Python code. You can’t refer to Node within the Node class. No, the workaround is to stringify "Node". class Node(Object): def add_sub(self, sub: 'Node'): ... def get_subs(self) -> Sequence['Node']: #Or maybe 'Sequence[Node]' works just fine. As of python3.7, this stringification is done by automatically under a from future import, and will ev…

> This is absolutely wrong! You cannot annotate a function as returning `auto` in C++.

You can do that since C++14.

Re: A Failed Experiment with Python Type Annotations

#16
Other people have mentioned that the self-referential case from this post is doable. But what is not doable (to my knowledge) is this kind of self-reference:

    class Node(typing.NamedTuple):  # or dataclass
        child: 'Node'
The error is example.py:4: error: Recursive types not fully supported yet, nested types replaced with "Any".

This error has been in there for several years at least. And it always bites me when I forget. It's particularly cryptic when the self-reference is many levels deep. I've even had the error message break in these cases where it prints out a line number from the wrong file. So, then you have to hunt to see where the self-reference is hiding.

Re: A Failed Experiment with Python Type Annotations

#17

> mypy has no trouble understanding this, but it’s unfortunately not valid Python code. You can’t refer to Node within the Node class. No, the workaround is to stringify "Node". class Node(Object): def add_sub(self, sub: 'Node'): ... def get_subs(self) -> Sequence['Node']: #Or maybe 'Sequence[Node]' works just fine. As of python3.7, this stringification is done by automatically under a from future import, and will ev…

"[...]You cannot annotate a function as returning `auto` in C++. `auto` and its variants in other languages are useful for eliding redundant type declarations. Especially long ones that use generics/templates. `auto foo = MyContainer>();` or whatever is nice than having to double write the type declaration. But, in C++ or java, if you write a function that returns a Mycontainer>, you have to write that in the function.[...]"

Maybe I'm misunderstanding something, but one can write a function auto foo() in C++ and the return type is inferred. Lambda functions infer the return type by default.

Re: A Failed Experiment with Python Type Annotations

#18

> mypy has no trouble understanding this, but it’s unfortunately not valid Python code. You can’t refer to Node within the Node class. No, the workaround is to stringify "Node". class Node(Object): def add_sub(self, sub: 'Node'): ... def get_subs(self) -> Sequence['Node']: #Or maybe 'Sequence[Node]' works just fine. As of python3.7, this stringification is done by automatically under a from future import, and will ev…

[deleted]

Re: A Failed Experiment with Python Type Annotations

#19
I recently added type annotations to my Python 3.7 project and found it very helpful. Just the process of adding the annotations caught a handful of bugs!

Some things I found useful:

1. from __future__ import annotations

As I mentioned in another comment, this lets you write annotations naturally without worrying about when something gets defined.

2. typing.TYPE_CHECKING is only True while type checking.

This allows you to conditionally import files that would otherwise cause a circular dependency so that you can use the symbols for annotations.

3. def foo(bar: str = None) -> str

If an argument defaults to None, then mypy will recognize that its type is actually Optional[whatever]. So in the example above, bar is an Optional[str]. (I'm not sure if this is mypy-specific.) Optional[T] is equivalent to Union[T, None].

4. You can make typedefs easily.

MyType = Union[Sequence[str], Dict[str, int]]

Makes writing complicated annotations easier.

Re: A Failed Experiment with Python Type Annotations

#20
post #17

> mypy has no trouble understanding this, but it’s unfortunately not valid Python code. You can’t refer to Node within the Node class. No, the workaround is to stringify "Node". class Node(Object): def add_sub(self, sub: 'Node'): ... def get_subs(self) -> Sequence['Node']: #Or maybe 'Sequence[Node]' works just fine. As of python3.7, this stringification is done by automatically under a from future import, and will ev…

"[...]You cannot annotate a function as returning `auto` in C++. `auto` and its variants in other languages are useful for eliding redundant type declarations. Especially long ones that use generics/templates. `auto foo = MyContainer >();` or whatever is nice than having to double write the type declaration. But, in C++ or java, if you write a function that returns a Mycontainer >, you have to write that in the funct…

Yuck, apparently I missed this happening. Its still (I think) true in java, where you can't have a function return `var`.
Post reply on HN