【问题标题】:MyPy Type Check variable with class type assigned None分配了类类型的 MyPy 类型检查变量 无
【发布时间】:2022-10-13 03:01:13
【问题描述】:

我正在尝试键入检查大型 python 代码库。其中一种情况是对变量类型为类但在初始化期间分配为 None 的变量进行类型检查。我添加了其他几个案例,其中 MyPy 将通过代码库而没有任何投诉

from typing import Union, Optional

class TestClass(object):

   def __init__(this, pValue:float = 0.0):
      # This line will fail with 'Incompatible types in assignment (expression 
      # has type "None", variable has type "TestClass")'
      this._test_class:TestClass = None
      this._test_a:Optional[TestClass] = None
      
   def doSomething(this) -> None:
      if not this._test_class == None:
         # Use of the Optional typing will cause this line tobytes
         # fail with 'Item "None" of "Optional[TestClass]" has 
         # not attribute "doCalculate"'
         new_val:float = this._test_a.doCalculate()
      
   def doCalculate(this) -> float:
      return 0.0
      
# Code below all pass
class ClassA(object):
   def __init__(this):
      this._test_class:ClassA = None
      pass
      
   def doSomething(this) -> None:
      if not this._test_class == None:
         new_val:float = this._test_class.doCalculate()
      
   def doCalculate(this) -> float:
      return 0.0
      
class ClassB(object):
   def __init__(this, pValue = 0.0):
      this._test_class:ClassB = None
      pass
   
   def doSomething(this) -> None:
      if not this._test_class == None:
         new_val:float = this._test_class.doCalculate()
      
   def doCalculate(this) -> float:
      return 0.0
      

我正在使用的 MyPy 版本是 0.971(编译:是)

为什么在类型检查期间,MyPy 会在 ClassType 上抛出一个错误,该错误传递了具有定义类型的值,但会在 ClassB 中传递大小写?

解决方案是从TestClass.__init__ 中删除浮点类型,但这违背了记录类型的目的。

【问题讨论】:

  • Optional[ClassType] 应该是解决方案。这正是它的用途。
  • 必须提供minimal reproducible example。你的mypy 版本可能也是必要的
  • Barmar,这是来自 MyPy 文档的建议。 Optional[TestClass](最初是 ClassType)会在类的其他地方产生不同的错误。我已经改进了这个例子,使其更加清晰。

标签: python python-3.x mypy


【解决方案1】:

进一步审查,能够发现解决方案。根据 Barmar,Optional 类型应该允许 None 和 object 类型。在示例中,还有一个用于检查 None 的语句

      if not this._test_class == None:
         new_val:float = this._test_a.doCalculate()

因为我使用了相等运算符(== 或 !=),所以这与使用 'is' 完全不同

为了使整个 TestClass 通过 MyPy 并启用严格检查,代码被修改为

from typing import Optional

class TestClass(object):

   def __init__(this, pValue:float = 0.0):
      this._test_class:Optional[TestClass] = None
      this._test_a:Optional[TestClass] = None
      
   def doSomething(this) -> None:
      if not this._test_a is None:
         new_val:float = this._test_a.doCalculate()
      if not this._test_class is None:
         new_val = this._test_class.doCalculate()
      
   def doCalculate(this) -> float:
      return 0.0

真正的 Python 对 ==、!= 和 is 运算符有很好的描述。 (见https://realpython.com/courses/python-is-identity-vs-equality/#:~:text=The%20%3D%3D%20operator%20compares%20the,the%20same%20object%20in%20memory.

【讨论】:

    猜你喜欢
    • 2019-08-10
    • 1970-01-01
    • 2021-01-13
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    相关资源
    最近更新 更多