python - 为什么列表列表不是序列列表?
问题描述
我创建了以下示例:
from typing import List, Sequence
class Circle:
pass
def foo(circle: Circle) -> Sequence[Circle]:
return_value: List[Circle] = [circle]
return return_value
def bar(circle: Circle) -> List[Sequence[Circle]]:
# Incompatible return value type (got "List[List[Circle]]", expected "List[Sequence[Circle]]")
return_value: List[List[Circle]] = [[circle]]
return return_value
为什么在期待 a 时返回 a 是可以List[Circle]
的Sequence[Circle]
,但在期待 aList[List[Circle]]
时却不能返回 a List[Sequence[Circle]]
?
更具体地说,当值是返回值时,为什么这不行?我想我理解为什么它不能作为参数,但我不明白为什么这个值不被接受为返回值。
文档给出了一个很好的例子来说明为什么List
s 是不变的:
class Shape:
pass
class Circle(Shape):
def rotate(self):
...
def add_one(things: List[Shape]) -> None:
things.append(Shape())
my_things: List[Circle] = []
add_one(my_things) # This may appear safe, but...
my_things[0].rotate() # ...this will fail
在这里,想法是如果你把你的List[Subclass]
并将它传递给认为它是 a 的东西List[Superclass]
,该函数可以编辑你的List[Subclass]
,以便它包含Superclass
元素,所以它在函数运行后变成a 。List[Superclass]
但是,作为返回值,我不明白为什么这是一个问题。一旦它退出该功能,每个人都会将其视为 a List[Sequence[Circle]]
,它就是这样,所以应该没有问题。
解决方案
再一次,在输入这个问题时,我想我已经找到了答案。
考虑以下情况:
from typing import List, Sequence
class Circle:
pass
def baz(circle_list_matrix: List[List[Circle]]) -> List[Sequence[Circle]]:
# Incompatible return value type (got "List[List[Circle]]", expected "List[Sequence[Circle]]")
return circle_list_matrix
在这里,Mypy 提出错误是绝对正确的,因为使用 的其他函数circle_list_matrix
可能依赖于它是 a List[List[Circle]]
,但之后的其他函数可能会将其修改为 a List[Sequence[Circle]]
。
为了确定我们所处的情况,Mypy 必须跟踪我们的变量何时被声明,并确保List[List[Circle]]
在函数返回之后将返回值视为 a (即使它是这样输入的)在允许我们将其用作返回值之前。
(请注意,List[List[Circle]]
在函数返回之前将其视为 a 不应该是一件坏事,因为List[List[Circle]]
在那些点上它是 a 。此外,如果它总是被视为 a List[Sequence[Circle]]
,那么我们可以直接输入它没有问题。当某些东西将其视为 a 时就会出现问题List[List[Circle]]
,例如 with circle_list_matrix[0].append(Circle())
,因此我们必须将其键入为 aList[List[Circle]]
才能执行该操作,但List[Sequence[Circle]]
在函数返回后每次都将其视为 a 。)
底线是 Mypy 不做那种分析。所以,为了让 Mypy 知道这没问题,我们应该直接转换它。
也就是说,我们知道返回值永远不会再被用作a List[List[Circle]]
,所以baz
应该写成:
def baz(circle_list_matrix: List[List[Circle]]) -> List[Sequence[Circle]]:
# works fine
return cast(List[Sequence[Circle]], circle_list_matrix)
从哪里cast
导入typing
。
可以bar
在问题代码中应用相同的铸造技术。
推荐阅读
- git - 如何共享排除目录?
- node.js - 在 mongoDB 中流式传输时 insertMany 无法正常工作
- c++11 - (解决用户错误)c++11 make_shared
(新类)内存泄漏 - flutter - 如果一个小部件声明为 const,它是否会传播给它的孩子?
- javascript - 如何在 ui-grid 角度选择中获取字符串的值并将其传递给 Spring 控制器
- python - 在python的元组中没有重复的随机选择
- html - 如何在使用 Bootstrap 4 加载页面后禁用加载器/微调器?
- javascript - Node.JS:具有多个不同 Socks5 问题的 Puppeteer 多线程实例
- scala - 在scala中覆盖父方法
- machine-learning - 值错误 - 检查目标时出错 - LSTM