【问题标题】:How to use Optional correctly when assigning to None?分配给None时如何正确使用Optional?
【发布时间】:2020-10-18 22:33:30
【问题描述】:

我遇到了与here 描述的类似问题,我可以通过以下示例重现该问题(使用 py3.8);我有两个这样的课程:

from typing import Optional


class B:
    def __init__(self, name):
        self.name = name


class A:

    def __init__(
        self,
        name: str,
        clb: Optional[B] = None,
    ):
        self.name = name

        if clb is not None:
            if isinstance(clb, B):
                self.clb = clb
            else:
                raise TypeError("clb has to be of type B.")
        else:
            self.clb = None

如果我现在这样做

mypy filename.py

我会收到

错误:赋值中的类型不兼容(表达式的类型为“None”, 变量的类型为“B”)

如果我这样做,我可以摆脱这个错误

self.name = name
self.clb = None

if clb is not None:
    ...

还有其他方法可以避免这个错误吗?

【问题讨论】:

  • 您可以尝试与您链接的问题相同的方法:使用Optional[B] 注释self.clb。或者重写你的逻辑,只对self.clb进行一次赋值
  • @Wombatz:是的,我可以,但是如果我想更新clb 的类型,我必须在两个地方更新它;不是戏剧性的,但也不是那么好......
  • @Cleb 请将此限制添加到问题本身。否则,它就是您自己链接的问题的完美副本。

标签: python typing mypy


【解决方案1】:

简单的解决方案是只在一个地方分配给变量。

def __init__(self, name: str, clb: Optional[B] = None):
    self.name = name
    self.clb = clb

在我看来,您应该完全摆脱 isinstance 支票。 Mypy 现在负责检查你的类型,手动检查有些多余。

【讨论】:

  • 如果我理解正确,当clbNone 时,这现在也会引发TypeError,但情况并非如此,因为它是一个可选参数。
  • 没错,我会从我的答案中删除支票。如果您需要它,请使用 MisterMiyagi 的回答
【解决方案2】:

将检查压缩为涵盖所有可能变体的单个测试。使用结果执行单个分配:

    if clb is None or isinstance(clb, B):
        self.clb = clb
    else:
        raise TypeError("clb has to be of type B.")

【讨论】:

    猜你喜欢
    • 2019-12-15
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 2020-01-17
    • 2021-03-18
    • 1970-01-01
    • 2021-02-21
    • 1970-01-01
    相关资源
    最近更新 更多