Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x Python类中带有正向引用的可选或联合,由mypy错误标记_Python 3.x_Mypy - Fatal编程技术网

Python 3.x Python类中带有正向引用的可选或联合,由mypy错误标记

Python 3.x Python类中带有正向引用的可选或联合,由mypy错误标记,python-3.x,mypy,Python 3.x,Mypy,我定义了一个带有类型注释的TreeNode类。对于\uuuu init\uuuu和某些类方法中的参数,它接受TreeNode或None。完整的代码在测试期间运行良好,但是当我用mypy检查它时,它列出了4个警告。我使用的是Python 3.7.4和mypy版本0.74 我使用可选的[“TreeNode”]和Union[“TreeNode”,None]关键字尝试了这个方法,但错误仍然存在。请注意,TreeNode周围的引号是必需的,因为它是在完全定义类型之前对类型的前向引用 from typing

我定义了一个带有类型注释的TreeNode类。对于
\uuuu init\uuuu
和某些类方法中的参数,它接受TreeNode或None。完整的代码在测试期间运行良好,但是当我用mypy检查它时,它列出了4个警告。我使用的是Python 3.7.4和mypy版本0.74

我使用可选的[“TreeNode”]和Union[“TreeNode”,None]关键字尝试了这个方法,但错误仍然存在。请注意,TreeNode周围的引号是必需的,因为它是在完全定义类型之前对类型的前向引用

from typing import *

class TreeNode():
    def __init__(self, value,
                 parent : Optional["TreeNode"]=None,
                 left_child : Optional["TreeNode"]=None,
                 right_child : Optional["TreeNode"]=None):
        self.value = value
        self.parent = parent
        self.left_child = None
        self.right_child = None
        self.update_children(left_child, right_child)

    def get_parent(self):
        return self.parent

    def set_parent(self, other):
        self.parent = other

    def update_children(self,
                        left_child : Optional["TreeNode"] = None,
                        right_child : Optional["TreeNode"] = None):
        # update parents in children, if left or right not None.
        if left_child:
            self.left_child = left_child
            self.left_child.set_parent(self)
        if right_child:
            self.right_child = right_child
            self.right_child.set_parent(self)

    def depth(self):
        pass # full code omitted for brevity
以下是mypy输出:

tree_node.py:25: error: Incompatible types in assignment (expression has type "TreeNode", variable has type "None")
tree_node.py:26: error: "None" has no attribute "set_parent"
tree_node.py:28: error: Incompatible types in assignment (expression has type "TreeNode", variable has type "None")
tree_node.py:29: error: "None" has no attribute "set_parent"
我还尝试了对mypy抱怨的代码进行以下修改,但没有成功:

        if left_child is not None:
            self.left_child = left_child
            self.left_child.set_parent(self)
        if right_child is not None:
            self.right_child = right_child
            self.right_child.set_parent(self)

问题是为什么我会出现这些错误,当我明确指出TreeNode或None都可以,并且只有当它不是None时才执行有问题的代码。

问题与您在构造函数中设置左和右子级的方式有关——具体来说,这两行:

self.left_child = None
self.right_child = None
由于这些字段被分配了
None
值,mypy最终保守地推断出这些字段的类型正好是
None
。而
可选[TreeNode]
不是
None
的子类型,因此
update\u children
中的赋值失败

(Mypy理论上可以观察到构造函数内部正在调用
update\u children
,并使用那里的赋值来推断字段的更准确类型,但这种逻辑实现起来相当困难。)

本例中的解决方法是显式地给这两个字段一个类型提示。例如,如果您使用的是Python 3.6+,则可以使用变量注释:

self.left_child: Optional[TreeNode] = None
self.right_child: Optional[TreeNode] = None
或者,如果希望支持较旧的Python版本,可以使用基于注释的语法:

self.left_child = None   # type: Optional[TreeNode]
self.right_child = None  # type: Optional[TreeNode]