预期类型 'List[A]'(匹配泛型类型 'List[_T]'),在正确键入的列表中得到 'List[B]' 而不是
Expected type 'List[A]' (matched generic type 'List[_T]'), got 'List[B]' instead on correctly typed lists
from typing import List
class Base(object):
pass
class A(Base):
pass
class B(Base):
pass
a: List[A] = []
b: List[B] = []
c: List[Base] = a + b
我在 b
收到 Expected type 'List[A]' (matched generic type 'List[_T]'), got 'List[B]' instead
。
我如何获得正确的警告,因为显然类型没问题。
这些类型都不行。 List
是不变的,这意味着 List[X]
是 而不是 替代 List[Y]
除非 X
和 Y
完全相同平等的。同样,A <: Base
并不意味着 List[A] <: List[Base]
并且 B
.
也是如此
PEP 484: Covariance and contravriance
[...]
By default generic types are considered invariant in all type variables, which means that values for variables annotated with types like List[Employee]
must exactly match the type annotation -- no subclasses or superclasses of the type parameter (in this example Employee
) are allowed.
虽然可以 re-interpret 此操作的类型,但这并不是明确的。保守的类型检查器将拒绝该操作而不是猜测。
像List
这样的可变容器是不变的,因为元素可以插入到(逆变)和从中取出 (协变)列表。如果不需要可变性,使用不可变 Sequence 提供有效的类型注释:
from typing import Sequence
a: Sequence[A] = []
b: Sequence[B] = []
c: Sequence[Base] = [*a, *b]
如果需要可变性,可以显式枚举要在 List
中找到的所有类型。这 pre-emptively 扩大了列表中预期的元素,即使每个单独的列表实际上只包含一种类型。
a: List[Union[A, B]] = []
b: List[Union[A, B]] = []
c: List[Union[A, B]] = a + b
Pre-emptively 扩大操作数的类型可能是不可取的或不可能的。或者,可以在使用地点 cast
它们。
a: List[A] = []
b: List[B] = []
c: List[Union[A, B]] = cast(List[Union[A, B]], a) + cast(List[Union[A, B]], a)
请注意,cast
有效地禁用了对转换值的类型检查。仅在已知正确的情况下使用它。
from typing import List
class Base(object):
pass
class A(Base):
pass
class B(Base):
pass
a: List[A] = []
b: List[B] = []
c: List[Base] = a + b
我在 b
收到 Expected type 'List[A]' (matched generic type 'List[_T]'), got 'List[B]' instead
。
我如何获得正确的警告,因为显然类型没问题。
这些类型都不行。 List
是不变的,这意味着 List[X]
是 而不是 替代 List[Y]
除非 X
和 Y
完全相同平等的。同样,A <: Base
并不意味着 List[A] <: List[Base]
并且 B
.
PEP 484: Covariance and contravriance
[...]
By default generic types are considered invariant in all type variables, which means that values for variables annotated with types likeList[Employee]
must exactly match the type annotation -- no subclasses or superclasses of the type parameter (in this exampleEmployee
) are allowed.
虽然可以 re-interpret 此操作的类型,但这并不是明确的。保守的类型检查器将拒绝该操作而不是猜测。
像List
这样的可变容器是不变的,因为元素可以插入到(逆变)和从中取出 (协变)列表。如果不需要可变性,使用不可变 Sequence 提供有效的类型注释:
from typing import Sequence
a: Sequence[A] = []
b: Sequence[B] = []
c: Sequence[Base] = [*a, *b]
如果需要可变性,可以显式枚举要在 List
中找到的所有类型。这 pre-emptively 扩大了列表中预期的元素,即使每个单独的列表实际上只包含一种类型。
a: List[Union[A, B]] = []
b: List[Union[A, B]] = []
c: List[Union[A, B]] = a + b
Pre-emptively 扩大操作数的类型可能是不可取的或不可能的。或者,可以在使用地点 cast
它们。
a: List[A] = []
b: List[B] = []
c: List[Union[A, B]] = cast(List[Union[A, B]], a) + cast(List[Union[A, B]], a)
请注意,cast
有效地禁用了对转换值的类型检查。仅在已知正确的情况下使用它。