mypy严格模式下二叉树操作函数报Optional[Tree]类型不匹配错误如何解决
问题原因
Tree类的left、right属性被声明为Optional[Tree]类型,允许为空,但to_rpn、evaluate函数要求入参必须是Tree类型。递归调用时你直接传入tree.left、tree.right,mypy无法自动识别「操作符节点必然存在左右子节点」的业务约束,因此抛出类型不兼容错误。
修复方案
方案1:添加运行时校验(推荐)
通过显式校验提前拦截非法的树结构,同时满足mypy的类型检查要求,生产环境也可以安全使用。
修改后完整代码如下:
from typing import Optional class Tree: def __init__(self, value: str, left: Optional['Tree'] = None, right: Optional['Tree'] = None): self.value = value self.left = left self.right = right def to_rpn(tree: Tree) -> str: if tree.value not in ("+", "*"): return tree.value # 校验操作符节点必须有左右子节点 if tree.left is None or tree.right is None: raise ValueError(f"操作符节点[{tree.value}]缺少子节点,树结构非法") return f"{to_rpn(tree.left)} {to_rpn(tree.right)} {tree.value}" def evaluate(tree: Tree) -> int: if tree.value == "+": if tree.left is None or tree.right is None: raise ValueError(f"操作符节点[{tree.value}]缺少子节点,树结构非法") return evaluate(tree.left) + evaluate(tree.right) elif tree.value == "*": if tree.left is None or tree.right is None: raise ValueError(f"操作符节点[{tree.value}]缺少子节点,树结构非法") return evaluate(tree.left) * evaluate(tree.right) else: return int(tree.value)
如果是开发测试场景,也可以用assert代替显式抛错,代码更简洁:
def to_rpn(tree: Tree) -> str: if tree.value not in ("+", "*"): return tree.value assert tree.left is not None and tree.right is not None return f"{to_rpn(tree.left)} {to_rpn(tree.right)} {tree.value}"
方案2:类型断言(仅适用于可100%保证树结构合法的场景)
如果你能确保所有操作符节点的左右子节点一定不为空,可以用cast直接告诉mypy类型,不需要额外运行时开销:
from typing import Optional, cast class Tree: def __init__(self, value: str, left: Optional['Tree'] = None, right: Optional['Tree'] = None): self.value = value self.left = left self.right = right def to_rpn(tree: Tree) -> str: if tree.value not in ("+", "*"): return tree.value left = cast(Tree, tree.left) right = cast(Tree, tree.right) return f"{to_rpn(left)} {to_rpn(right)} {tree.value}" def evaluate(tree: Tree) -> int: if tree.value == "+": left = cast(Tree, tree.left) right = cast(Tree, tree.right) return evaluate(left) + evaluate(right) elif tree.value == "*": left = cast(Tree, tree.left) right = cast(Tree, tree.right) return evaluate(left) * evaluate(right) else: return int(tree.value)
两种方案都可以通过mypy --disallow-any-explicit --strict的检查。
内容的提问来源于stack exchange,提问作者user11574067
相关产品推荐
相关产品推荐

