【问题标题】:How do I tell MyPy that a parameter is not optional?如何告诉 MyPy 参数不是可选的?
【发布时间】:2018-06-11 18:48:54
【问题描述】:

我有一个对象src 和一个可选对象dest。如果dest 没有传递给函数,则创建一个新的MyObj 并将其传递给另一个函数。

使用mypy==0.610 这是给我的:

错误:“copy_data”的参数 2 具有不兼容的类型“Optional[MyObj]”;预期“MyObj”

我如何告诉 MyPy destcopy_data 函数中不是可选的?

from typing import Optional


class MyObj(object):
    def __init__(self, name):
        self.name = name

def new_obj(name):
    # type (str) -> MyObj
    return MyObj(name=name)

def copy_stuff(src, dest=None, fname=None):
    # type: (MyObj, Optional[MyObj], Optional[str]) -> MyObj
    if not dest:
        dest = new_obj(fname)
    my_obj = copy_data(src, dest)
    return my_obj

def copy_data(src, dest):
    # type: (MyObj, MyObj) -> MyObj
    return dest

【问题讨论】:

  • 如果您在copy_stuff 中创建一个单独的局部变量来保存MyObj 实例,是否仍然会引发错误?
  • 啊,真的很高兴dest = dest or new_obj(fname)
  • 这似乎是我的类型检查。你能提供一个最小的可重复样本吗?你用的是什么版本的 mypy?
  • @ethanhs 我在v0.610添加了一个对我来说失败的 MVE
  • 为什么要检查 not dest 而不是 dest is not None

标签: python mypy


【解决方案1】:

这里的错误在new_obj。您在类型注释中缺少一个冒号。我通过在你的 MVE 中添加一些 reveal_types 来解决这个问题:

def new_obj(name):
    # type (str) -> MyObj
    #     ^ ERROR is here
    return MyObj(name=name)

def copy_stuff(src, dest=None, fname=None):
    # type: (MyObj, Optional[MyObj], Optional[str]) -> MyObj
    reveal_type(new_obj)  # E: Revealed type is 'def (name: Any) -> Any'
    if not dest:
        reveal_type(dest)  # Optional[MyObj]
        dest = new_obj(fname)
        reveal_type(dest)  # Optional[MyObj]
    my_obj = copy_data(src, dest)
    return my_obj

当从返回 Any 的函数分配时,Mypy 似乎保留了 Optional[MyObj] 类型。修复类型注释后,它可以按预期工作。

【讨论】:

  • 这似乎是正确的,并且肯定修复了 MVE。我仍然想知道为什么它可以与 dest = dest or new_obj(fname) 一起使用
  • 因为如果dest不是None,它会计算为dest,如果是,表达式的第一部分计算为假,所以表达式的第二部分,@ 987654330@,通过了。由于它的类型为Any,因此被接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-27
  • 2023-02-15
  • 2018-08-16
  • 1970-01-01
  • 2020-04-02
  • 2020-10-17
  • 1970-01-01
相关资源
最近更新 更多