先打个广告:欢迎关注我的公众号,参与 文史大挑战 趣味题目。使用方法见 这篇文章 。
正文开始:
对于任意深度的数学表达式,希望使用 Python 解析,然后按照某种规则处理其中的元素。这里最终结果只是对单个元素的字面处理,而没有涉及表达式的表示和运算。
问题
任意数学表达式,包含数字、变量、四则运算符、函数名称、括号等符号,比如下面的例子:
A * (B + 3) / SUM(C+D)
我们希望按照任意的规则去处理其中的某些类型的符号,比如:
- 去掉函数名称,得到
A*(B+3)/(C+D)
- 替换变量,得到
AA*(BB+3)/SUM(CC+DD)
分词-Tokenize
首先我们需要设计一个函数把表达式的每个符号分隔开,并且根据字面量的值来判断所属的类型,跟我们人类观察的方法完全一样。比如下面的表达式
A * (B + 3) / SUM(C+D)
我们从左往右观察的时候,心里会想:
A → 字母 → 变量
空格 → 忽略 → 忽略
\* → 属于[+-*/]中的一种 → 运算符
( → 属于[()]中的一种 → 括号
B → 字母 → 变量
….以此类推
那么需要设计一个 tokenize()
函数,将原始表达式逐个按照字符的字面量划分类型。同时,将这个函数设计为生成器,使代码更简洁高效。代码如下:
def tokenize(s):
toks = re.compile(r' +|[\d\.]+|[A-Za-z_0-9]+|[\(\)]|[\+\-\*\/]')
for match in toks.finditer(s):
s = match.group(0)
if s[0] == ' ':
continue
elif s[0] in '()':
yield (s, s)
elif s[0].isdigit():
yield ('NUMBER', s)
elif s[0].isalpha():
yield ('FUNC', s)
elif s[0] == '[':
yield ('COUNTER', s)
elif s[0] in '+-*/':
yield ('OPER', s)
else:
yield ('OTHER', s)
下面看看这个函数的运行过程:
首先创建的正则表达式,用多个 |
或符号分隔多种情况,包括:空格( +
)、带小数点的数字([\d\.]+
)、字母数字混合([A-Za-z_0-9]+
)、小括号([\(\)]
)、四则运算符([\+\-\*\/]
)
finditer()
返回一个迭代器,每次迭代返回的内容是一个 Match Object,Match Object 的 group()
函数返回分组的结果,参数为 0 时,返回完整的匹配结果。
接下来根据匹配内容的第一个字符来判断所属的类型:
如果您对本文有疑问或者寻求合作,欢迎 联系邮箱 。邮箱已到剪贴板
标签: PYTHON
给个免费的赞吧~
精彩评论
本站 是个人网站,采用 署名协议 CC-BY-NC 授权。
欢迎转载,请保留原文链接 https://www.lfhacks.com/tech/python-expression-parser/ ,且不得用于商业用途。