我正在尝试使用 python 的 textx 模块来解释语法的语言原型。 我正在创建一个像这样的模型:
from textx import metamodel_from_str
funl_grammar = """
Model: statement *= Statement;
Statement: FunctionDefinition | Function;
FunctionDefinition: name=ID '=' function=Function;
Function: name=ID '(' params*=Param (',' params*=Param)* ')';
Param: Function | INT | ID | STRING;
Comment: /#.*$/;
ID: /[a-zA-Z_][a-zA-Z0-9_]*/;
INT: /[0-9]+/;
STRING: /".*"/;
"""
mm = metamodel_from_str(funl_grammar)
现在我的问题是,如何使用 mypy 对它进行类型检查?
如果我创建一个像这样的函数,我想确保参数是我的语法的一部分并且textx 认为它是
Param
:
def my_func(param: mm["Param"]):
...
我收到 mypy 错误
error: Name "Param" is not defined [name-defined]
你知道我该如何解决这个问题吗?谷歌搜索和 ChatGPT 到目前为止没有帮助。
在使用 mypy 对使用 textX 生成的模型进行类型检查时遇到完全正确的问题。问题在于 mypy 在运行时之前不知道 textX 生成的类的类型信息,因为这些类是动态生成的。
让我们探索一些可以解决这个问题的方法:
1. textX 的类型提示(推荐)
从 textX 2.6.0 版开始,可以直接在语法中使用类型提示,mypy 可以理解这些提示。这提供了最佳的集成和类型安全性。
- 修改的语法: 在的 textX 语法中添加类型提示。需要为属性指定类型,并且可以选择为规则本身指定返回类型。
from textx import metamodel_from_str
funl_grammar = """
Model: statement*=Statement;
Statement: FunctionDefinition | Function;
FunctionDefinition: name=ID '=' function=Function;
Function: name=ID '(' params*=Param[','] ')' # 返回类型可以省略
;
Param: Function | int | str; # 使用内置类型
Comment: /#.*$/;
ID: /[a-zA-Z_][a-zA-Z0-9_]*/;
INT: /[0-9]+/;
STRING: /".*"/;
"""
mm = metamodel_from_str(funl_grammar)
-
使用生成的模型:
现在,可以使用 mypy 检查的
my_func
。
def my_func(param: mm['Param']):
...
2. 运行时检查与断言
如果无法使用 textX 2.6.0 或更新版本,可以依靠运行时检查和断言来提高类型安全性。
- 检查类型并使用断言:
def my_func(param):
if not isinstance(param, mm['Param']):
raise TypeError("Expected Param type")
# ... your function logic
这种方法不会在编译时提供类型检查,但如果传递了错误类型的参数,它会在运行时捕获错误。
其他注意事项:
-
生成的代码检查: 可能还想探索使用
generate
方法从的 textX 模型生成 Python 代码,然后对生成的代码运行 mypy。但是,这需要额外的步骤,并且不如直接类型提示方便。 -
自定义类型提供程序: 对于更复杂的场景,可以考虑实现自定义 mypy 类型提供程序,以在运行时提供 textX 模型的类型信息。这很高级,需要对 mypy 插件有深入的了解。
我希望这些方法可以帮助使用 mypy 对的 textX 模型实现类型安全!如果有任何其他问题,请告诉我。
标签:python,python-typing,mypy,textx From: 78829635