如何使用 mypy 注释具有额外属性的类型?

问题描述

我有一个 ast.UnaryOp 对象,但我手动添加了一个 parent 属性(请参阅 answer)。如何在函数中对此进行注释?

我目前只有:

def _get_sim206(node: ast.UnaryOp):
    if isinstance(node.parent,ast.If):
        return False
    return True

但 mypy 抱怨(理所当然)ast.UnaryOp 没有 parent 属性。

我如何告诉 mypy node 不是 ast.UnaryOp 而是 ast.UnaryOp + parent attribute

我的尝试

我创建了自己的 UnaryOp 类,它具有父属性。我可以用它来进行类型转换:

class UnaryOp(ast.UnaryOp):
    def __init__(self,orig: ast.UnaryOp) -> None:
        self.op = orig.op
        self.operand = orig.operand
        self.lineno = orig.lineno
        self.col_offset = orig.col_offset
        self.parent: ast.Expr = orig.parent  # type: ignore

它的缺点是我需要在很多地方输入类型转换并且我引入了 Any。如果我可以在某处声明该文件中的所有 ast.* 类型确实具有 parent 属性

解决方法

作为一种解决方法,您可以将 isinstance()protocol 一起使用 @runtime_checkable 修饰,这将在运行时检查所有协议成员是否已定义并确保静态正确性。

from typing import Protocol,runtime_checkable,cast
import ast


@runtime_checkable
class ParentProto(Protocol):
    parent: ast.AST
    

def foo(node: ast.UnaryOp):
    if isinstance(node,ParentProto):
        # use node.parent
        p = node.parent
        l = node.lineno
# assignment
g = ast.UnaryOp()
cast(ParentProto,g).parent = ast.If()

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...