You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Inferring a more precise type on assignment to a variable with Any type #2928
Mypy infers the type Any for y after the second assignment:
from typing import Any
def f(x: Any) -> None:
y = x
y = 1
reveal_type(y) # Any
Inferring int as the type might be less surprising. However, if a variable is explicitly declared with an Any type, such as x in the above example, it's less clear what would be the right thing to do.
A more general solution would allow redefining variables with arbitrary new types (#1174).
It seems that in general variables whose initial type is Any are untouched by the binder and always remain typed as Any? That doesn't feel right or consistent. IMO it should mean that anything can be assigned to such a variable, not that we should ignore tracking assignments.
As a work-around, if the initial type is object you can also assign anything to a variable, and it does get tracked by the binder. But I don't like the long-lasting effect of Any here.
One thing to note is that we don't distinguish between variables that have type annotations and variables that set their type from the first assignment. The example would look a lot more reasonable if it was:
fromtypingimportAnydeff(x: Any) ->None:
y=x# type: Anyy=1reveal_type(y) # Any
In this case example (where the type is explicit), I don't think it makes sense to reduce Any's use as an escape hatch. There's an argument to be made for behaving differently with and without an explicit type annotation, but that comes with a cost in complexity and user education. My initial inclination is it's not worthwhile here.
This is an old argument (so far carried out in private I think) but I don't think the explicit # type: Any should override the subsequent assignment of a value of a given type either. I like to see the analogy between
y = x # (inferred or declared Any)
y = 1
reveal_type(y)
and
y = x # (inferred or declared Any)
assert isinstance(y, int)
reveal_type(y)
I think both of these should reveal the same type (int).
(In fact, if anything, the assert has less of a runtime guarantee about y's "int-less" than the straight assignment, since python -O doesn't compile code for assert.)
This would be nice to fix, on one hand. On the other hand, this could generate a lot of false positives in existing code that type checks cleanly, so I'm not sure if fixing this is actually worth it.
Activity
gvanrossum commentedon Mar 1, 2017
It seems that in general variables whose initial type is
Anyare untouched by the binder and always remain typed asAny? That doesn't feel right or consistent. IMO it should mean that anything can be assigned to such a variable, not that we should ignore tracking assignments.As a work-around, if the initial type is
objectyou can also assign anything to a variable, and it does get tracked by the binder. But I don't like the long-lasting effect ofAnyhere.JukkaL commentedon Mar 1, 2017
The
Anytype can come from a skipped module, so usingobjectis not a good workaround in general.ddfisher commentedon Mar 2, 2017
One thing to note is that we don't distinguish between variables that have type annotations and variables that set their type from the first assignment. The example would look a lot more reasonable if it was:
In this case example (where the type is explicit), I don't think it makes sense to reduce
Any's use as an escape hatch. There's an argument to be made for behaving differently with and without an explicit type annotation, but that comes with a cost in complexity and user education. My initial inclination is it's not worthwhile here.gvanrossum commentedon Mar 2, 2017
This is an old argument (so far carried out in private I think) but I don't think the explicit
# type: Anyshould override the subsequent assignment of a value of a given type either. I like to see the analogy betweenand
I think both of these should reveal the same type (
int).(In fact, if anything, the
asserthas less of a runtime guarantee abouty's "int-less" than the straight assignment, sincepython -Odoesn't compile code forassert.)JukkaL commentedon Jan 28, 2020
This would be nice to fix, on one hand. On the other hand, this could generate a lot of false positives in existing code that type checks cleanly, so I'm not sure if fixing this is actually worth it.
hauntsaninja commentedon Dec 30, 2025
Fixed by #18538