'Missing return statement' 在简单的条件结构中

'Missing return statement' in simple conditional structure

下面函数的 return 类型取决于传递给 path 的参数:如果它是 None 函数 return 是一个字符串,如果它是一个string 函数 returns None,在所有其他可能的情况下,函数根本不 return。但是,mypy 报告

error: Missing return statement

我在这里错过了什么?

import json
from typing import Optional

def to_json(data: dict, path: Optional[str] = None) -> Optional[str]:
    if path is None:
        return json.dumps(data)
    elif isinstance(path, str):
        with open(path, 'w') as file:
            json.dump(data, file)
    else:
        raise TypeError('Unsupported type for ``path``.')

只需在代码中添加 return None 或在代码末尾添加 return -1 或任何此类 return。

没有明确地从所有分支返回一些东西会使静态分析失败:它被视为一个遗漏(并且被认为是不好的做法)。

只需在 else 部分中明确 return None(不需要在你提出异常的地方)

elif isinstance(path, str):
    with open(path, 'w') as file:
        json.dump(data, file)
    return None

首先,您的代码是有效的 python。我相信 mypy 似乎是根据 PEP8 对 return 的建议进行配置的,但由于它必须强制执行类型检查,因此对其更加严格。相关栏目:

Be consistent in return statements. Either all return statements in a function should return an expression, or none of them should. If any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable).

是:

def foo(x):
    if x >= 0:
        return math.sqrt(x)
    else:
        return None

否:

def foo(x):
    if x >= 0:
        return math.sqrt(x)

因此,对于您的代码,只需在您没有 return 任何其他内容的所有分支中明确 return None

mypy 默认情况下会警告缺少 return 类型,因此您可以明确关闭它:

$ mypy --no-warn-no-return spam.py

或仅关闭对特定行的特定检查:

def to_json(data: Dict, path: Optional[str] = None) -> Optional[str]:  # type: ignore[return]
    ...

但是,您的函数具有不同的 return 类型,具体取决于输入。我会添加一个重载签名来处理这些:

from typing import Dict, Optional, overload

# when path is provided, the function returns
@overload
def to_json(data: Dict, path: str) -> str: ...

# when path is not provided, the function returns None
@overload
def to_json(data: Dict) -> None: ...

# your actual impl
def to_json(data, path=None):
    if path is None:
        ...