Why if TYPE_CHECKING?
vickiboykis.com
vickiboykis.com
from __future__ import annotations
Then you will not get this error (NameError: name 'Sequence' is not defined) because it will not need the reference to `Sequence` for the annotation but the annotation is simply a string.Using `if TYPE_CHECKING` is also useful when you want to speed up the module load time by not importing unnecessary modules (unnecessary at module load time).
And then, also to resolve import cycles, where you still want to annotate the function argument types.
One problem though: If this is a type/object which is not needed for module load time (there it's just used to annotate some function arg type), but which will be needed inside the function, type checkers and IDEs (e.g. PyCharm) will not show any problem, but then at runtime, you will the NameError once it tries to use the type/object.
Example module:
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import torch
def agi_model(query: torch.Tensor) -> torch.Tensor:
torch.setup_secret_agi()
...
This module will load just fine, because `torch` is only needed for type checking at module load time. However, once you call this `agi_model` function, it will fail because `torch` is actually unknown at runtime. However, no IDE will show any problem with this code. (Edit: Eclipse/PyDev handles it correctly now, see answer below.)Then you would add another `import torch` inside that `agi_model` function. However, then the IDE might even complain that this hides the outer scope `torch`.
That's not entirely True... I just checked it here and Eclipse/PyDev does flag this correctly -- since version 11.0.0 ;)
See: https://www.pydev.org/history_pydev.html (Imports found inside a typing.TYPE_CHECKING will be considered undefined if the scope that uses it requires it to be available when not type-checking).
If you don't do runtime typechecking in the entire program, sure.
[1] Except some light scripting
``` import type {foo} from ... ```
E.g. for `import { SomeType } from "backend-server"`, you don't want to include your entire server code in the frontend just because you imported the response type of some JSON API. `import type` neatly solves this issue, and it even enforces that you can't import anything but types from your backend.
I also want to state that TS already removes regular `import`s that only import types. `import type` is mostly used to help bundlers. https://www.typescriptlang.org/docs/handbook/release-notes/t...
Pet peeve: Python is compiled (into bytecode), so it could theoretically do checks at compile time. The "dynamically-typed" part is correct and is the real reason.
A compilation translates a language to another, whether it is native code, internal bytecode, portable bytecode, or another source language. Compilation might also type check and optimize depending on the language. Interpretation executes a language; normally bytecode is executed, but pure source level interpreters exist. Native code is "interpreted" by the cpu itself of course.
For example JAVA is certainly a compiled language, but it is typically compiled to bytecode and then interpreted or JITed (which is a combined interpreter/compiler).
Someone took the interpreted JavaScript language, added typing syntax on top, and typing can be checked statically.
The Python team took the interpreted Python language, added typing syntax on top, and here we are reading a claim that it can't be checked statically because it's interpreted. You understand my puzzlement.
Or does Deno run TS natively? At a glance it looks like even its runtime is written in JS[0].
EDIT: looks like they have bindings for V8[1] so yeah, just a JS interpreter behind the scenes.
> Python doesn’t care about types at runtime
This should say "Python doesn't care about type annotations at runtime."
Python _does_ care about types at runtime - but it doesn't use type annotations to compute them.
That doesn't detract from what's otherwise a really clear and helpful post. Python is living through a schizophrenic period in its evolution, and it's causing some problems. I hope it gets ironed out, though don't underestimate the difficulty. Python remains my go-to for many problems: a joy to use (for me) in many cases. But I definitely feel the need for static typing as codebase size increases. Having type annotations is good, but not being able to rely on them (i.e. static typing is not sound) adds to cognitive load and detracts from a confident development experience.
I will add that, in my experience, having type annotations that are unreliable, cumbersome, with so many edge cases and requiring this kind of magic (e.g. "if TYPE_CHECKING", etc) which is beyond most "casual" Python users effectively means type annotations are a very hard sell for most non-hardcore team mates.
I've been in a position to try improving processes and code quality of the Python codebase, and introducing mypy and type annotations has always been a very hard sell. The team just won't accept the benefits, given the difficulties in using it. If only Python made it easier and more reliable, but the current state is a mess.
I come from the static typing world, so of course I see the benefits. But most/all of my team mates don't, and so they see this as some really odd hoops I want them to jump through, for minimal benefit (in their eyes).
Yes it does. All Python source code is parsed and compiled into bytecode. SyntaxError is raised before runtime.
Without a correct syntax there is no way to assign meaning or execute or interpret, etc.
It's fine to have implicit circular dependencies in Python because duck typing means that every function is effectively generic. Type annotations eliminate this and turn Python into a fundamentally different language.
Type annotations aren't just extra boilerplate in function signatures, they also have these sorts of knock-on effects.
What do you mean? Where is the cycle?
class Parent:
children : List[Child]
class Child:
__init__(self, parent: Parent):Are you talking about a specific pattern or implementation detail in the interpreter? Because I would not call this "dependency"...
At the core of the problem is the fact that there's no thing as "partial import" in Python. When you do "from M import A" in Python, all the contents of M are evaluated and a reference to A is added to the current namespace. So, cyclic dependencies arise sooner or later, unless you adopt some very un-pythonic style for your codebase (e.g. one file per class).
You're in Python. Either embrace it or use another language.
On the contrary, I joyfully read and write code with type annotations. It is obviously very useful knowing which object types a function expects and which it will return.
The way python does it is different. There's no "typethon". The python grammar was simply extended to allow any random expression as a "type".
In fact:
x: print("hi") = 4
is valid python, and it does print "hi" without even so much as a warning. Personally, I don't think "print(hi)" should be a valid type.The fact that the typescript implementation does not run typescript directly, and cPython does not type check before running the code, are both implementation details.
Typescript is just a better type system on top of javascript than python's type system is on top of untyped python, because typescript is a cohesive design rather than a collection or random stuff accumulated over time.
There's no reason that couldn't have happened for python, it just didn't.
And it isn't:
a.py:1: error: Invalid type comment or annotation [valid-type]
a.py:1: note: Suggestion: use print[...] instead of print(...)
Found 1 error in 1 file (checked 1 source file)As stated in the typing documentation [0]: "the only legal parameters for type are classes, Any, type variables, and unions of any of these types".
I can put that in main.py and do `python3 main.py` and it will simply run fine.
What is the point of this whole system if it's not enforced?
If you don't want type checking, don't run mypy.
I don't see what's so difficult. If it was technically possible to run programs that have type errors in other languages, they would have the option to ignore type errors too, because it's convenient.
Typescript also ignores errors (generating js output for you to run) by default, so what's the point if it's not enforced?
PHP has been able to add in more typing over the same period of time and has seemed to avoid these Python problems.
Python also broke backwards compatibility with their v3 release years ago. Unsure why breaking backward compatibility is being called out here(?).
But yeah, overall, it's struck me that PHP has introduced more and stricter typing rules with surprisingly little impact (compared to what could have been, of course).
Do you mean mypy is optional?
At the risk of opening a can of worms here, what's "horrible"?
In your own PHP code, you can get by without any typing at all. If/when you start to use 3rd party libraries, that may become a factor, though off the top of my head I can't think of a show stopper.
I doubt many people picked Python "because it has types". It was picked because it was the right tool for the job.
Type hints were bolted on after the fact, and even in their limited form provide TONS of value for some people (myself included).
If you don't want them don't use them, but I doubt there is a project which uses Python specificially because it has type hints.
I think in a lot of cases only the more general form of this statement is true, i.e.:
- it is a tool
- it was picked
- there was a job
For me, that's the benefit of typing in python (as shonky as it is) -- you can use it to help write better library code, then ignore the types (except as accurate documentation) when using those libraries.
Maybe there are other languages that can do this, but the ones i know all have their own downsides.
You obviously don't get the haskell experience, where if your program type checks it's probably correct, but the alternative (if, remember, you want a dynamically typed scripting language) is no type checking, which is definitely worse for some people.
Running pyright in CI/CD and in vscode has considerably improved the quality of my code, especially when refactoring.
I do strongly believe that leaving the type checking to a third party program is a terrible idea. I also believe that it should at least be possible to opt-in to type-checking the annotations at runtime during execution (at the very least for tests).