Array
as a type and trying to find a generic base type of "A" which it can't find because it doesn't exist
it
is an iterable of an unspecified type.class Foo:
def __init__(self, it):
self.it = it
def __iter__(self):
return self
def __next__(self):
return next(self.it)
for i in Foo(iter(range(10))):
print(i)
a: List[Optional[int]] = [None, None]
a[0] = 5
a[1] = 10
b: int = 0
if a[0] != None:
b = a[0]
It shows an Error:
test.py:12: error: Incompatible types in assignment (expression has
type "Optional[int]", variable has type "int")
Found 1 error in 1 file (checked 1 source file)
I do check if a[0] is not None
but I don't know why it still fails to narrow down the type of a[0] from int | None
to int
as the condition for None
is already checked for.
any idea why?
I think the answer here is that it's not possible, but I'd like to be able to do the equivalent of a Typescript typeof
for a function. An example:
def foo(i: int) -> str:
return "foo"
class Bar:
def __init__(self, fn: "foo"):
self.captured = fn
def baz(self):
return self.captured("123")
So the fn
parameter in Bar
constructor I'd like to enforce as matching the signature of foo
(somehow). Obviously I could write a separate Callable
or protocol, but this feels like duplication.
ParametersOf
approach) but I think the gap is more about the ergonomics of being able to lift a type from some other variable. Like uses_same_type_as_x: TypeOf[x] = ...
(where in this example x
happens to be a function) . Had a look through the PEPs and couldn't find anything along those lines. Wonder if a mypy plugin could do this...
if else
operator alternation of types compatible with Callable[[Iterable], Sequence]
gives incompatible type builtins.object
:#!/usr/bin/python3.9
from typing import Callable, Iterable, Sequence
deterministic: bool = True
processlist1: Callable[[Iterable], Sequence] = sorted
processlist2: Callable[[Iterable], Sequence] = list
processlist3: Callable[[Iterable], Sequence] = sorted if deterministic else list
reveal_type(sorted)
reveal_type(list)
reveal_type(sorted if deterministic else list)
Python-tests$ mypy --show-error-code creator-callable.py
creator-callable.py:8: error: Incompatible types in assignment (expression has type "object", variable has type "Callable[[Iterable[Any]], Sequence[Any]]") [assignment]
creator-callable.py:10: note: Revealed type is 'Overload(def [_LT <: builtins._SupportsLessThan] (typing.Iterable[_LT`-1], *, key: None =, reverse: builtins.bool =) -> builtins.list[_LT`-1], def [_T] (typing.Iterable[_T`-1], *, key: def (_T`-1) -> builtins._SupportsLessThan, reverse: builtins.bool =) -> builtins.list[_T`-1])'
creator-callable.py:11: note: Revealed type is 'Overload(def [_T] () -> builtins.list[_T`1], def [_T] (iterable: typing.Iterable[_T`1]) -> builtins.list[_T`1])'
creator-callable.py:12: note: Revealed type is 'builtins.object'
Found 1 error in 1 file (checked 1 source file)
...if its reproduceable in 3.8...
@jwood:mozilla.org thank you, I did not know that the current mypy does not support Python 3.9. I have changed the shebang to#!/usr/bin/python3.8
(I am using the default Python in Ubuntu 20.04:Python 3.8.5
) and run mypy with Python 3.8 explicitly. The result is the same :(Python-tests$ python3.8 -m mypy --show-error-code creator-callable.py creator-callable.py:8: error: Incompatible types in assignment (expression has type "object", variable has type "Callable[[Iterable[Any]], Sequence[Any]]") [assignment] creator-callable.py:10: note: Revealed type is 'Overload(def [_LT <: builtins._SupportsLessThan] (typing.Iterable[_LT`-1], *, key: None =, reverse: builtins.bool =) -> builtins.list[_LT`-1], def [_T] (typing.Iterable[_T`-1], *, key: def (_T`-1) -> builtins._SupportsLessThan, reverse: builtins.bool =) -> builtins.list[_T`-1])' creator-callable.py:11: note: Revealed type is 'Overload(def [_T] () -> builtins.list[_T`1], def [_T] (iterable: typing.Iterable[_T`1]) -> builtins.list[_T`1])' creator-callable.py:12: note: Revealed type is 'builtins.object' Found 1 error in 1 file (checked 1 source file)
sorted([5, None])
reveal_type(5 if random() else "asdf")
reveals object
(as opposed to Union[str, int]
)
Hi, is mypy drawing a wrong conclusion in the following example?
```from typing import Literal, runtime_checkable, Protocol
@runtime_checkable
class A(Protocol):
x: Literal[0]
class B:
x: Literal[0, 1]
class C(B):
x: Literal[1]
b = B()
if isinstance(b, A): # error: Subclass of "B" and "A" cannot exist: would have incompatible method signatures [unreachable]
b.x = 0 # error: Statement is unreachable [unreachable]```
First, it says: "would have incompatible ... signatures". IMO, it should say: "could have incompatible ... signatures".
Second, it handles the last line as (definitely) unreachable and does not analyse it further. However, it is just eventually unreachable, and mypy thus misses the definite bug in the last line.
C1
):from abc import abstractmethod
from typing import *
class A0:
f: ClassVar[Literal[0]] = 0
class A1:
f: ClassVar[Literal[1]] = 1
class B:
@property
@abstractmethod
def f(self) -> Literal[0, 1]:
...
def t(self) -> None:
if isinstance(self, A0): # error: Subclass of "B" and "A0" cannot exist: would have incompatible method signatures [unreachable]
...
class C1(A0, B):
...
reveal_type(C1().f) # Revealed type is 'Literal[0]'
class C2(B, A0): # Definition of "f" in base class "B" is incompatible with definition in base class "A0" [misc
...
reveal_type(C2().f) # Cannot instantiate abstract class 'C2' with abstract attribute 'f' [abstract]
To me, it seems like this is valid but produces an error in MyPy:
class BaseDict(TypedDict):
a: str
class CustomDict(BaseDict):
b: str
def my_general_fun(x: BaseDict) -> None:
print(x[“a”], x.get(“b”))
MyPy will not allow this because BaseDict has no attribute ”b”
. But isn’t the point of .get
to get an attribute that might be missing?
get
and known, but if it’s not known, it should return Any
(or at the very least, the second part of the get or None)
from typing import Union, TypedDict
def func(arg: Union[str, int]):
print(arg)
class Type(TypedDict, total=False):
a: str
b: int
c = Type({"a": "a", "b": 2})
for val in c.values():
func(val)