Invariance vs covariance
Most mutable generic collections are invariant, and mypy considers alluser-defined generic classes invariant by default(see Variance of generic types for motivation). This could lead to someunexpected errors when combined with type inference. For example:
- class A: ...
- class B(A): ...
- lst = [A(), A()] # Inferred type is List[A]
- new_lst = [B(), B()] # inferred type is List[B]
- lst = new_lst # mypy will complain about this, because List is invariant
Possible strategies in such situations are:
- Use an explicit type annotation:
- new_lst: List[A] = [B(), B()]
- lst = new_lst # OK
- Make a copy of the right hand side:
- lst = list(new_lst) # Also OK
- Use immutable collections as annotations whenever possible:
- def f_bad(x: List[A]) -> A:
- return x[0]
- f_bad(new_lst) # Fails
- def f_good(x: Sequence[A]) -> A:
- return x[0]
- f_good(new_lst) # OK