Python类型注解理解问题

Python Type Annotation Understanding Problem

我对 python 类型注释有一点理解上的问题。考虑以下用于将字典转换为标准化格式的函数

from __future__ import annotations  # needed for type annotations in > python 3.7
from typing import Dict, List, Union


class Producer(object):
    pass

def normalize_producers(
    producers: Dict[str, Union[Producer, List[Producer]]]
) -> Dict[str, List[Producer]]:
    """
    Function to normalize producer input to have the same format
    """
    normalized_dict: Dict[str, List[Producer]] = {}
    for key in producers.keys():
        if isinstance(producers[key], list):
            normalized_dict[key] = producers[key]
        else:
            normalized_dict[key] = [producers[key]]
    return normalized_dict

此示例导致分配 normalized_dict:

的类型问题
Argument of type "Producer | List[Producer]" cannot be assigned to parameter "v" of type "List[Producer]" in function "__setitem__"
  Type "Producer | List[Producer]" cannot be assigned to type "List[Producer]"
    "Producer" is incompatible with "List[Producer]"

Argument of type "list[Producer | List[Producer]]" cannot be assigned to parameter "v" of type "List[Producer]" in function "__setitem__"
  TypeVar "_T@list" is invariant
    Type "Producer | List[Producer]" cannot be assigned to type "Producer"
      "List[Producer]" is incompatible with "Producer"

但是,当我使用临时列表并检查该列表的类型时,没有出现类型问题:

def normalize_producers_save(
    producers: Dict[str, Union[Producer, List[Producer]]]
) -> Dict[str, List[Producer]]:
    """
    Function to normalize producer input to have the same format
    """
    normalized_dict: Dict[str, List[Producer]] = {}
    for key in producers.keys():
        templist = producers[key]
        if isinstance(templist, list):
            normalized_dict[key] = templist
        else:
            normalized_dict[key] = [templist]
    return normalized_dict

这是否意味着,虽然我将 producers 的值指定为 ProducerList[Producer] 类型,但 if isinstance(producers[key], list): 不会导致 producers[key] 总是类型列表?我不明白,第一个版本的功能有什么问题。

这是 mypy 中已知的 issue,它不会像 dict_var[key] 那样缩小索引表达式的类型。作为解决方法,您可以为字典值使用显式变量:

from __future__ import annotations  # needed for type annotations in > python 3.7
from typing import Dict, List, Union


class Producer(object):
    pass

def normalize_producers(
    producers: Dict[str, Union[Producer, List[Producer]]]
) -> Dict[str, List[Producer]]:
    """
    Function to normalize producer input to have the same format
    """
    normalized_dict: Dict[str, List[Producer]] = {}
    for key, value in producers.items():
        if isinstance(value, list):
            normalized_dict[key] = value
        else:
            normalized_dict[key] = [value]
    return normalized_dict