代码之家  ›  专栏  ›  技术社区  ›  Veltzer Doron

是否在实例化时设置了Python3.x dictionary lint type check(typing)

  •  1
  • Veltzer Doron  · 技术社区  · 8 年前

    我有一个配置字典,我用dunder init调用层次结构中的值加载它,每个调用都实例化配置的一部分。试图添加打字到这个我收到了一个奇怪的行为(或可能我做错了什么)。我得到的行为与字典给出的类型一致,这些类型只在第一次声明中插入到字典中,更新扩展和添加键似乎不会改变字典在访问时声明的类型,这是我为说明问题而编写的一个简单代码:

    import re
    
    
    def foo(a: int = 1, b: str = "b"):
        d = {"a": a}
        d.update({"b": b})
        print(re.findall(d["b"], "baba"))
    
    
    foo()
    

    课程代码工作和输出 ['b', 'b'] (无意双关语)但是我的小妖精发出了两个警告:

    1. 在更新行: Unexpected type(s):<br>(Dict[str, str])<br>Possible types:<br>(Mapping[str, int])<br>(Iterable[Tuple[str, int]])
    2. 在Finditer线上: Expected type 'Union[bytes, str, __Regex]', got 'int' instead

    我的问题是,我对这个原因的分析是真的吗(dict将其类型设置为实例化)?有没有一种蟒蛇式的方法来修复这些警告?

    1 回复  |  直到 8 年前
        1
  •  2
  •   Michael0x2a    8 年前

    更新扩展和添加键似乎不会更改字典声明的类型

    这是故意的。如果有声明为类型的变量 Dict[str, int] ,如果您不小心尝试运行类似于 var['foo'] = 'bar' 是的。

    在这种情况下,因为你 d 对于字符串到整数的dict,mypy假设您希望该类型只是 dict[字符串,整数] 是的。

    如果希望代码键入check,则有几个选项:

    1. 明确声明您希望字典的值是什么类型,并使用断言或强制转换来确认某些键的类型是您希望它们是什么类型:

      def foo(a: int = 1, b: str = "b") -> None:
          d: Dict[str, Union[int, str]] = {"a": a}
          d.update({"b": b})
      
          # If you want to check your assumption at runtime
          b_regex = d["b"]
          assert isinstance(b_regex, str)
          print(re.findall(b_regex, "baba"))
      
          # If you don't want/don't need to check the type
          print(re.findall(cast(str, d["b"]), "baba"))
      
    2. 放弃静态输入dict,并使其值为 the dynamic 'Any' 以下内容:

      def foo(a: int = 1, b: str = "b") -> None:
          d: Dict[str, Any] = {"a": a}
          d.update({"b": b})
          print(re.findall(d["b"], "baba"))
      
    3. 使用 TypedDict mypy extension 指示dict只包含特定的字符串键,其中每个键都有特定类型的对应值。

      请注意,这是目前仅mypy的扩展,尽管有计划在不久的将来将其作为正式类型添加到pep 484中。一旦发生这种情况,pycharm实际上有义务理解typeddict(尽管他们可能已经提前加入了支持,但还不确定)。