如何将可变变量视为“易失性”进行静态类型检查?

问题描述 投票:0回答:1

考虑这个类,它有一个变量

state
,在方法
check_twice
中比较两次,并且它的值在方法
work
的两次检查之间发生变化:

import enum


class State(enum.Enum):
    INIT = 0
    DONE = 1


class Worker:
    def __init__(self) -> None:
        self.state = State.INIT

    def work(self):
        self.state = State.DONE

    def check_twice(self) -> None:
        if self.state is State.DONE:
            print("DONE at first try")
            return

        self.work()

        if self.state is State.DONE:
            # according to mypy this will not happen
            x: int = "x"  # mypy will not check this
            print("DONE at second try")
            return

        print("not DONE after second try")


if __name__ == "__main__":
    w = Worker()
    w.check_twice()

正如预期的那样,执行此操作时,输出为

$ python3 volatile.py 
DONE at second try

因为在

check_twice
开始时,变量仍然是
INIT
,但在第二次检查时,它已被
DONE
“在后台”更改为
work()

但是,根据mypy(版本1.5.0),当使用

--strict-equality
选项时,打印此输出的分支是无法访问的,

$ mypy --strict-equality volatile.py 
volatile.py:23: error: Non-overlapping identity check (left operand type: "Literal[State.INIT]", right operand type: "Literal[State.DONE]")  [comparison-overlap]

因为 mypy 认为如果

state
在第一次检查时为
DONE
,则该方法返回,并且在该方法的其余部分中
state
的唯一可能值是
INIT
(通过类型缩小)。它没有考虑到该值仍然可以通过其他代码更改为
DONE
并“优化掉”第二个
if self.state is State.DONE
语句。

可以通过添加

# type: ignore [comparison-overlap]
来消除该错误。但是,mypy 仍然不会检查该
if
语句的其余部分,其中包含明显的类型错误,并且不会生成错误消息。

我们如何向 mypy(或其他类型检查器)指示变量在访问一次后可以更改其值,并且必须检查第二个

if
语句的主体,类似于例如C语言中的
volatile
关键字?

python mypy python-typing
1个回答
0
投票

可以通过将比较移至(本地)函数来强制再次评估变量:

async def check_twice(self) -> None:

    def done() -> bool:
        return self.state is State.DONE

    if done():
        print("DONE at first try")
        return

    await asyncio.sleep(0.2)

    if done():
        x: int = "x"  # mypy will now check this
        print("DONE at second try")
        return

    print("not DONE after second try")

现在 mypy 将报告第二个

if
语句中的类型错误:

$ mypy --strict-equality volatile.py 
volatile.py:32: error: Incompatible types in assignment (expression has type "str", variable has type "int")  [assignment]
© www.soinside.com 2019 - 2024. All rights reserved.