Right, but it seems like PyTorch could have annotated all of these call functions using a ParamSpec and return value annotation thereby making __call__ have the same annotation as forward.
a: int|float = 12
# later...
a = 3.14
If you left the type checker to infer aâs type, it would choose int. In practice, the need for this is rare - I mostly see it when declaring instance variables that default to None: self.count: int|None = None
Thatâs not always the case. Sometimes, you are fine with the type of the variable being inferred from the type of value assigned to them. Sometimes, you want an error to be raised if you know that, e.g., a should be an int and b should be a bool, but it turns out you use the wrong function to initialize them or the definition of the function has changed at some point.
OK, I went through the entire thread and I donât think allowing the syntax outside of assignments has been brought up yet.
While this would be a syntax error:
a: int, b: bool = fun()
Why not just do one annotation per line? A personal opinion, but I think itâs better style.
There seems to be a lot of ideas over the last few years that revolve around save one line here or there while making code harder to read. I think this is a false economy.
Too be honest, in that case I just donât write a type annotation. Itâs just overkill (even for me).
I have a personal framework, where I often use the following:
tm_id: int
work_tag: str
tm_id, work_tag = self.path_args # path_args is tuple[Any, ...]
# or even
tm_id: int
(tm_id, ) = self.path_args
I would personally prefer the following style, instead of spreading the variable definitions over multiple lines - and thereby putting more emphasis on them than they are worth:
tm_id: int, work_tag: str = self.path_args
# or
(tm_id: int,) = self.path_args
Personally, I would do this:
tm_id, work_tag = self.path_args
assert isinstance(tm_id, int)
assert isinstance(work_tag, str)
but I admit it depends on prevalence and context. Itâs possible you may also be better doing match self.path_args.
One option that hasnât been brought up yet is to do it on one line using cast.
When the return type depends on the arguments. Ideally function return type should be merged with explicit annotations. Like so:
from typing import Mapping
from matplotlib.axes import Axes
import matplotlib.pyplot as plt
fig, axes: Mapping[Any, Axes] = plt.subplots(2, 2)
subplots is annotated to return tuple[Figure, Any], so fig and axes should now be typed as Figure and Mapping respectively.
You can already write
a: int; b: bool
a, b = fun()
I wouldnât recommend it, like most usages of ;.
subplots is annotated to return tuple[Figure, Any], so fig and axes should now be typed as Figure and Mapping respectively.
Isnât it an array of axes? Anyway, polymorphic returns like this are usually poor interface design. Someone tried to save a comma and created headaches.
Isnât it an array of axes?
If you call plt.subplots(1, 1, ....) then the result is tuple[Figure, Axes] (a single axes object), unless you also pass squeeze=False. I donât think anyone would accuse matplotlib of having a great interface, but at this point itâs hard to change it.
Yes, I know how it works. Itâs a bad interface. So I donât think itâs a good justification for the proposed feature.
Agreed. I just thought you were asking about the type of the return value. ![]()
Isnât it an array of axes? Anyway, polymorphic returns like this are usually poor interface design. Someone tried to save a comma and created headaches.
Exactly. Therefore, I believe the proposed feature offers a simple and consistent solution to alleviate the headaches caused by code created by others, especially when it is difficult or time-consuming to fix their code.
Exactly. Therefore, I believe the proposed feature offers a simple and consistent solution to alleviate the headaches caused by code created by others, especially when it is difficult or time-consuming to fix their code.
Personally, Iâd rather push people to write good interfaces, than make it easier to work around bad
ones. But I understand your point.
So, for this, Iâd rather just do the annotations on a different line for these (somewhat rare) cases.
Itâs a bad interface. So I donât think itâs a good justification for the proposed feature.
The feature already exists, what is discussed is a natural extension of it, and I personally would love to see it to be extended to for loops.
Iâd rather push people to write good interfaces, than make it easier to work around bad ones.
The best is the enemy of good. Python is a very flexible language used for prototyping and by people without CS degrees so I wouldnât expect it to become a model of properly crafted and annotated interfaces any time soon, or ever.