下面的代码运行良好-
from typing import List, Dict, Any
def func1(input_list: List[Dict[str, Dict[str, str]]],):
for config_dict in input_list:
table_1 = ".".join(
(
config_dict.get("src").get("db"), # line 6
config_dict.get("src").get("schema"), # line 7
config_dict.get("src").get("table_name"), # line 8
)
)
print(table_1)
if __name__ == "__main__":
func1(
[
{
"src": {
"db": "db",
"schema": "abc",
"table_name": "bcd",
},
"trgt": {
"db": "dd",
"schema": "asd",
"table_name": "fds",
},
}
]
)
但是当我在上面运行mypy时,我得到了以下错误
> mypy abc.py
abc.py:6: error: Item "None" of "Optional[Dict[str, str]]" has no attribute "get" [union-attr]
abc.py:7: error: Item "None" of "Optional[Dict[str, str]]" has no attribute "get" [union-attr]
abc.py:8: error: Item "None" of "Optional[Dict[str, str]]" has no attribute "get" [union-attr]
我错过了什么吗?我想保持input_list结构不变。
mypy --version
mypy 0.991 (compiled: yes)
2条答案
按热度按时间7fhtutme1#
dict.get
的返回值具有Optional[Dict[str, str]]
类型,这意味着它 * 可以 * 在运行时返回None
,所以不能无条件地假设返回值具有get
方法,这就是mypy
为您捕获的错误。您可以通过首先 * 检查 * 返回值是否为
dict
来修复此问题。这是
mypy
可以执行类型收缩的一个例子,它假设如果在s is None
之后执行,则s
不是None
,因此它的类型可以从Optional[Dict[str,str]]
“收缩”(更改为更具体的子类型)到Dict[str, str]
。您也可以停止使用
get
,而改用__getitem__
。在这里,键查找失败是由异常指示的,而不是由特定的返回值指示的,因此类型收缩也会被执行。(只有在不引发异常时才会到达以下代码)s4n0splo2#
您的函数注解太宽泛:它允许dict列表中的键与函数的期望值不匹配,可以使用
typing.TypeDict
来代替Dict[str, str]
,更具体一些,你仍然需要检查config_dict.get("src")
返回的是TableConfig
,而不是None
,但是你可以假设TableConfig
的值 * 确实 * 有你想要使用的三个键。(正如我的另一个答案一样,我将切换到config_dict["src"]
,让查找通过异常而不是特殊的返回值失败。)如果
"src"
和"target"
不是任意键,而是模式的一部分,您甚至可以更具体地说明。