用python写计算器代码_仅用50行代码实现一个Python编写的计算器的教程

更新时间:2023-07-28 12:54:43 阅读: 评论:0

⽤python写计算器代码_仅⽤50⾏代码实现⼀个Python编写的
计算器的教程
简介
在这篇⽂章中,我将向⼤家演⽰怎样向⼀个通⽤计算器⼀样解析并计算⼀个四则运算表达式。当我们结束的时候,我们将得到⼀个可以处理诸如 1+2*-(-3+2)/5.6+3样式的表达式的计算器了。当然,你也可以将它拓展的更为强⼤。
我本意是想提供⼀个简单有趣的课程来讲解 语法分析 和 正规语法(编译原理内容)。同时,介绍⼀下PlyPlus,这是⼀个我断断续续改进了好⼏年的语法解析 接⼝。作为这个课程的附加产物,我们最后会得到完全可替代eval()的⼀个安全的四则运算器。
如果你想在⾃家的电脑上试试本⽂中给的例⼦的话,你应该先安装 PlyPlus ,使⽤命令pip install plyplus  。(译者注:pip是⼀个包管理系统,⽤来安装⽤python写的软件包,具体使⽤⽅法⼤家可以百度之或是google之,就不赘述了。)
本篇⽂章需要对python的继承使⽤有所了解。
语法
对于那些不懂的如何解析和正式语法⼯作的⼈⽽⾔,这⾥有⼀个快速的概览:正式语法是⽤来解析⽂本的⼀些不同层⾯的规则。每⼀个规则都描述了相对应的那部分输⼊的⽂本是如何组成的。
这⾥是⼀个⽤来展⽰如何解析1+2+3+4的例⼦:
一棵苹果树Rule #1 - add IS MADE OF add + number
OR number + number
或者⽤ EBNF:
add: add'+'number
| number'+'number
;
解析器每次都会寻找add+number或者number+number,找到⼀个之后就会将其转换成add。基本上⽽⾔,每⼀个解析器的⽬标都在于尽可能的找到最⾼层次的表达式抽象。
以下是解析器的每个步骤:
number + number + number + number
第⼀次转换将所有的Number变成“number”规则
[number + number] + number + number
解析器找到了它的第⼀个匹配模式!
[add + number] + number
在转换成⼀个模式之后,它开始寻找下⼀个
[add + number]
add
这些有次序的符号变成了⼀个层次上的两个简单规则: number+number和add+number。这样,只需要告诉计算机如果解决这两个问题,它就能解析整个表达式。事实上,⽆论多长的加法序列,它都能解决! 这就是形式⽂法的⼒量。
运算符优先级
这相当于:
1 + (
2 *
3 / 4) - 5 + 6省考职位
我们可以通过嵌套规则表⽰此语法中的结构:
add: add+mul
| mul'+'mul
;
mul: mul '*; number
| number'*'number
;
通过将add设为操作mul⽽不是number,我们就得到了乘法优先的规则。
让我们在脑海中模拟⼀下使⽤这个神奇的解析器来分析1+2*3*4的过程:
number + number * number * number
number + [number * number] * number
解析器不知道number+number的结果,所以这是它(解析器)的另⼀个选择
number + [mul * number]
number + mul
现在我们遇到了⼀点困难! 解析器不知道如何处理number+mul。我们可以区分这种情况,但是如果我们继续探索下去,就会发现有很多不同的没有考虑到得可能,⽐如mul+number, add+number, add+add, 等等。
那么我们应该怎么做呢?
幸运的是,我们可以做⼀点⼩“把戏”:我们可以认为⼀个number本⾝是⼀个乘积,并且⼀个乘积本⾝
是⼀个和!
这种思路⼀开始看起来有点古怪,不过它的确是有意义的:
add: add'+'mul
| mul'+'mul
| mul
;
mul: mul'*'number
| number'*'number
| number
;
但是如果 mul能够变成 add, 且 number能够变成 mul , 有些⾏的内容就变得多余了。丢弃它们,我们就得到了:
add: add'+'mul
mul: mul'*'number
| number
;
让我们来使⽤这种新的语法来模拟运⾏⼀下1+2*3*4:
number + number * number * number
现在没有⼀个规则是对应number*number的了,但是解析器可以“变得有创造性”
number + [number] * number * number
number + [mul * number] * number
number + [mul * number]
[number] + mul
[mul] + mul
[add + mul]
add
成功了
如果你觉得这个很奇妙,那么尝试着去⽤另⼀种算数表达式来模拟运⾏⼀下,然后看看表达式是如何⽤正确的⽅式来⼀步步解决问题的。或者等着阅读下⼀节中的内容,看看计算机是如何⼀步步运⾏出来的!
运⾏解析器
现在我们对于如何让我们的语法运作起来已经有了⾮常不错的想法了,那就写⼀个实际的语法来应⽤⼀下吧:
复制代码 代码如下:
start: add;            // 这是最⾼层
add: add add_symbol mul | mul;
mul: mul mul_symbol number | number;
number:'[d.]+';      // ⼗进制数的正则表达式
mul_symbol:'*'|'/';// Match * or /
add_symbol:'+'|'-';// Match + or -
你可能想要复习⼀下正则表达式,但不管怎样,这个语法都⾮常直截了当。让我们⽤⼀个表达式来测试⼀下吧:
>>>fromplyplusimportGrammar
>>> g=Grammar("""...""")
>>>printg.par('1+2*3-5').pretty()
start
add
add
number英语句子摘抄简短
1
add_symbol
+
mul
mul
number
2
mul_symbol
*
学生的number
3
add_symbol
-
mul青菜英文
number
5
⼲得漂亮!
仔细研究⼀下这棵树,看看解析器选择了什么层次。
如果你希望亲⾃运⾏这个解析器,并使⽤你⾃⼰的表达式,你只需有Python即可。安装Pip和PlyPlus之后,将上⾯的命令粘贴到Python内(记得将'...'替换为实际的语法哦~)。
使树成形
Plyplus会⾃动创建⼀棵树,但它并不⼀定是最优的。将number放⼊到mul和将mul放⼊到add⾮常有利于创建⼀个阶层,现在我们已经有了⼀个阶层那它们反⽽会成为⼀个负担。我们告诉Plyplus对它们加前缀去“展开”(i.e.删除)规则。
碰到⼀个@常常会展开⼀个规则,⼀个#则会压平它,⼀个?会在它有⼀个⼦结点时展开。在这种情况下,?就是我们所需要的。
行政职务怎么填写
start: add;
add: add add_symbol mul | mul; // Expand add if it's just a mul
mul: mul mul_symbol number | number;// Expand mul if it's just a number
number:'[d.]+';
mul_symbol:'*'|'/';
add_symbol:'+'|'-';
在新语法下树是这样的:
>>> g=Grammar("""...""")
add
add
number
1
add_symbol
+
兔耳朵怎么做mul
number
2
mul_symbol
*
钟表王国
number
3
add_symbol
-
number
5
哦,这样变得简洁多了,我敢说,它是⾮常好的。
括号的处理及其它特性
⽬前为⽌,我们还明显缺少⼀些必须的特性:括号,单元运算符(-(1+2)),及表达式中间允许存在空字符。其实这些特性都很容易就能实现,下⾯我们来尝试⼀下。
需要先引⼊⼀个重要的概念:原⼦。在⼀个原⼦⾥⾯(括号中及单元运算)发⽣的所有操作都优先于所有加法或乘法运算(包括位操作)。由于原⼦只是⼀个优先级的构造器,并⽆语法意义,帮我们加上"@"符号以确保在编译时它被能展开。
允许空格出现在表达式内最简单的⽅法就是使⽤这种解释⽅式:add SPACE add_symbol SPACE mul | mul;  但个解释结果啰嗦且可读性差。所有,我们需要令Plyplus总是忽略空格。
下⾯是完整的语法,包容了以上所述特性:
start: add;
add: (add add_symbol) mul;
mul: (mul mul_symbol) atom;
@atom: neg | number |'('add')';
neg:'-'atom;
number:'[d.]+';
mul_symbol:'*'|'/';

本文发布于:2023-07-28 12:54:43,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1099868.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:语法   表达式   解析器
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图