为了避免打字问题,我经常遇到同样的问题.

例如,我有一个函数x,它很少返回值None,其他时候它返回int.


def x(i: int) -> Union[int, None]:
    if i == 0:
        return
    return i

def test(i: int):
    a = x(i)
    # typing issue: *= not supported for types int | None and int
    a *= 25

x在代码库中经常使用,大多数时候i已经被判断了一百次,x(i)确实会返回int而不是None. 使用它作为int立即创建键入警告—例如,你不能乘以可能的None值.

这个案子的最佳做法是什么?

我考虑过的 idea 是:

  1. 没有真正意义的判断它Noneif a is None: return,因为它已经known.
  2. a *= 25 # type: ignore将使a成为Unknown类型.
  3. a = x(i) # type: int次警告就会消失.但会创建一个新的警告"int| None不能分配给int "
  4. a = cast(int, x(i))个,还没试过很多.

我通常会将返回类型x改为int,在return # type: ignore中添加ignore,并在文档字符串中提到它可以返回None,这有助于避免类型警告污染整个代码库.这是最好的办法吗?

def x(i: int) -> int:
    """might also return `None`"""
    if i == 0:
        return # type: ignore
    return i

推荐答案

在这种情况下,异常可能比您从未期望到达的返回语句更好.

def x(i: int) -> int:
    if i == 0:
        raise ValueError("didn't expect i==0")
    return i

def test(i: int):
    try:
        a = x(i)
    except ValueError:
        pass

    a *= 25

确信已充分验证了x的参数的代码可以省略try语句.

静态来说,这是准确的:if x返回,它保证返回一个int.(它是否会回来是另一个问题.


理想情况下,您可以定义一个像NonZeroInt这样的细化类型,并将i == 0转换为类型错误,而不是值错误.

# Made-up special form RefinementType obeys
#
#  isinstance(x, RefinementType[T, p]) == isinstance(x, T) and p(x)
NonZeroInt = RefinementType[int, lambda x: x != 0]

def x(i: NonZeroInt) -> int:
    return i

x(0)  # error: Argument 1 to "x" has incompatible type "int"; expected "NonZeroInt"  [arg-type]

i: int = 0
x(i)  # same error

j: NonZeroInt = 0  #  error: Incompatible types in assignment (expression has type "int", variable has type "NonZeroInt")  [assignment]

x(j)  # OK

k: NonZeroInt = 3  # OK
x(k)  # OK

Python相关问答推荐

如何使用Google Gemini API为单个提示生成多个响应?

使用plotnine和Python构建地块

Python在tuple上操作不会通过整个单词匹配

替换字符串中的多个重叠子字符串

如何使用pandasDataFrames和scipy高度优化相关性计算

将特定列信息移动到当前行下的新行

SQLGory-file包FilField不允许提供自定义文件名,自动将文件保存为未命名

try 将一行连接到Tensorflow中的矩阵

Python—从np.array中 Select 复杂的列子集

递归访问嵌套字典中的元素值

通过ManyToMany字段与Through在Django Admin中过滤

如何杀死一个进程,我的Python可执行文件以sudo启动?

合并与拼接并举

为什么在FastAPI中创建与数据库的连接时需要使用生成器?

Beautifulsoup:遍历一个列表,从a到z,并解析数据,以便将其存储在pdf中.

Polars表达式无法访问中间列创建表达式

遍历列表列表,然后创建数据帧

Stats.ttest_ind:提取df值

如何在表单中添加管理员风格的输入(PDF)

按最大属性值Django对对象进行排序