Live data from Hacker News

Python Type Checker Comparison: Empty Container Inference

pyrefly.org

41–50 of 59 posts

Re: Python Type Checker Comparison: Empty Container Inference

#41
post #4

I can't help but find type hints in python to be..goofy? I have a colleague who has a substantial C++ background and now working in python, the code is just littered with TypeAlias, Generic, cast, long Unions etc.. this can't be the way..

I strongly disagree. Python has actually done a decent job of adding type annotations into the language IMO. If you ignore the bit where they don't actually specify their semantics anyway. > this can't be the way.. The alternative is fragile and unmaintainable code. I know which I prefer!

the alternative should be using a real statically-typed language instead of glorified comments that don't do anything without outside tools.

I understand that very large code bases have been built in python and this is a compromise to avoid making them rewrite Ks upon Ks of LoC but as it stands, Python type annotations are akin to putting a Phillip's head screwdriver on a ball peen hammer; the screwdriver is not a real screwdriver and the ergonomics of the hammer have been compromised.

Re: Python Type Checker Comparison: Empty Container Inference

#42

Earlier quoted context omitted.

It's not "mildly annoying". I don't enable strict mode on multiple projects because people don't want to type anything outside of function signatures. Inferring the type from the first use is 100% the correct choice because this is what users want 99% of the time, for the rest you can provide type information.

Annotating empty collections is one of the few places you need to annotate outside function signatures. It's not a big deal. It doesn't happen that often.

And, when it does, you can just put them when the empty container is assigned:

    things: set[tuple[str, str, int]] = set()
    users: list[User] = []
Many people don't seem to know this exists.

Re: Python Type Checker Comparison: Empty Container Inference

#43
post #4

Earlier quoted context omitted.

I strongly disagree. Python has actually done a decent job of adding type annotations into the language IMO. If you ignore the bit where they don't actually specify their semantics anyway. > this can't be the way.. The alternative is fragile and unmaintainable code. I know which I prefer!

the alternative should be using a real statically-typed language instead of glorified comments that don't do anything without outside tools. I understand that very large code bases have been built in python and this is a compromise to avoid making them rewrite Ks upon Ks of LoC but as it stands, Python type annotations are akin to putting a Phillip's head screwdriver on a ball peen hammer; the screwdriver is not a re…

Well yes I agree using Rust or whatever would be better, but if your options are Python or Python with type hints, then the latter gets you closest to proper static typing. They're really not that bad with Pyright in strict mode. Mypy is rubbish.

Re: Python Type Checker Comparison: Empty Container Inference

#44
post #30
post #3

I think it would be worth mentioning that in normal use (strict mode) Pyright simply requires you to add type annotations to the declaration. Occasionally mildly annoying but IMO it's clearly the best option.

Requiring the annotations on empty containers is the only way to have type safety if the type checker cannot infer the type of the container, like Pyright. If the type checker can infer a type then the annotation would only be required if the inferred type doesn't match the user's intent, which means one would need to add fewer annotations to an arbitrary working-but-unannotated program to satisfy the type checker.

Yes but also having more complicated type inference makes the actual type checking less useful as a check. You see that in languages with global type inference too.

Adding explicit types strategically (e.g. in function signatures) tells the compiler (and readers) explicitly what the type should be, so if you add code that violates that it gives you an error instead of silently inferring a different type.

Re: Python Type Checker Comparison: Empty Container Inference

#45
post #36
post #6

My favorite part about the type annotations in python is that it steers you into a sane subset of the language. I feel like it's kind of telling that python is this super dynamic language but the type annotations aren't powerful enough to denote all that craziness.

The type hints are not even enforced at runtime. They are mostly documentation.

They can be used at runtime though. I wrote typedload, to load external data (json/bson/yaml) into python typed objects. In this way you know that if the data doesn't match the expectations you will have an exception at a specific point in the code, and after that it's safe to use the objects, rather than having to manually check at every access.

Now there are several other libraries that do this thing, but at the time (python3.5 and 3.6) it was the only option.

Re: Python Type Checker Comparison: Empty Container Inference

#46
post #28
post #24

Earlier quoted context omitted.

Python does not need that, as it has built-in type annotation support. The annotation is any expression, so you can in theory express anything a custom type-only language would allow you (although you could make it less verbose and easier to read). However, the it IMHO just works much worse than TS because: * many libraries still lack decent annotations * other libraries are impossible to type because of too much dyn…

Thanks for helping me understand. I wasn't aware of Python's type annotation support. I did some quick research and learned that type annotations don't cause compile errors even when there are type errors. Is that why type checkers like Pyrefly exist?

Yes, but there are also runtime type checkers that can be used to check that input data conforms to the expected types (aka a schema but defined using python types and classes).

Re: Python Type Checker Comparison: Empty Container Inference

#47
post #45
post #36

Earlier quoted context omitted.

The type hints are not even enforced at runtime. They are mostly documentation.

They can be used at runtime though. I wrote typedload, to load external data (json/bson/yaml) into python typed objects. In this way you know that if the data doesn't match the expectations you will have an exception at a specific point in the code, and after that it's safe to use the objects, rather than having to manually check at every access. Now there are several other libraries that do this thing, but at the ti…

That seems to handle deserialization? But would it protect you from assigning a value of the wrong type to the object later on?

Re: Python Type Checker Comparison: Empty Container Inference

#48
post #47
post #45

Earlier quoted context omitted.

They can be used at runtime though. I wrote typedload, to load external data (json/bson/yaml) into python typed objects. In this way you know that if the data doesn't match the expectations you will have an exception at a specific point in the code, and after that it's safe to use the objects, rather than having to manually check at every access. Now there are several other libraries that do this thing, but at the ti…

That seems to handle deserialization? But would it protect you from assigning a value of the wrong type to the object later on?

It must be used in combination with a static checker to be useful.

So you can do like a = typedload.load(json_data, int) and then "a" is considered to be an int and at runtime will be an int.

Of course your static checker should prevent you from doing a + "string" later on because that would fail.

Re: Python Type Checker Comparison: Empty Container Inference

#49
post #25

Earlier quoted context omitted.

Because Python decided that (for the usual New Jersey reason, simplicity of implementation) bool should just be an integer type the Liskov criterion comes into play. If we can X an integer and we've agreed bool is an integer => we can X a bool. That's not what booleans are but hey, it's sorta close and this was easier to implement. So, can we add two bools together? Adding booleans together is nonsense, but we've sai…

> So, can we add two bools together? Adding booleans together is nonsense, but we've said these are a kind of integer so sure, I guess True + True = 2 ? And this cascades into nonsense like ~True being a valid operation in Python and its result is true... The bitwise negation is indeed janky and inaccurate, but True + True = 2 is absolutely a valid thing to say in boolean algebra. Addition mean "or", and multiplicati…

> True + True = 2 is absolutely a valid thing to say in boolean algebra

Nope. The Boolean algebra only has two values, and it lacks the addition operation entirely.

Re: Python Type Checker Comparison: Empty Container Inference

#50

Earlier quoted context omitted.

Because Python decided that (for the usual New Jersey reason, simplicity of implementation) bool should just be an integer type the Liskov criterion comes into play. If we can X an integer and we've agreed bool is an integer => we can X a bool. That's not what booleans are but hey, it's sorta close and this was easier to implement. So, can we add two bools together? Adding booleans together is nonsense, but we've sai…

Out of curiosity, I tried running `~True` in a Python 3.14.2 repl and got this output (the -2 is part of the output): >>> ~True :1: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you reall…

Yes, the article I was reading was about proposals to er, undeprecate this feature. Reasoning that well, sure it's obviously a footgun - but it works for integers and we've said bools are integers so...
Post reply on HN