Python中,默认有个函数名为eval
。这个函数在诸多像我一样的菜鸡圈子里,是很少用的。我也一直以为这个没什么特别大的作用。直到今天,我在读一个源代码的时候,突然意识到这个函数的用途。
由于水平有限,如果认为不对的地方,欢迎在评论区指出。
下面是我用pyqt实现的计算器代码(可能需要在这个源代码文件目录下,放一个特定图片文件,换上特定的名字然后作为图片。如果想要直接运行,也可以把这个地方给注释掉)
用Python3
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QToolTip, QLineEdit, QMessageBox, QDesktopWidget, QTextEdit
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtCore import QCoreApplication
class Calculater(QWidget):
def __init__(self):
super().__init__()
self.setUI()
def setUI(self):
QToolTip.setFont(QFont('SansSerif', 10))
Font = QFont('SansSerif', 18)
self.resize(500, 400)
self.move(100, 100)
self.setWindowTitle("Calculater")
self.setWindowIcon(QIcon('./1.jpg'))
self.center()
self.line = QLineEdit(self)
self.line.resize(480, 80)
self.line.move(10, 10)
self.line.setFont(Font)
self.Text = QTextEdit(self)
self.Text.resize(480, 280)
self.Text.move(10, 110)
self.Text.setFont(Font)
self.Text.setText(str(0))
self.line.textChanged.connect(self.calculate)
self.show()
def calculate(self):
s = self.line.text()
if len(s) == 0:
self.Text.setText(str(0))
return False
s = s.replace('^', '**') # 使得能够接受^这样的用法
try:
ans = eval(s)
except:
return False
else:
self.Text.setText(str(ans))
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Calculater()
sys.exit(app.exec_())
在上面的代码中,是实现我输入一个表达式的过程中就自动显示结果。
至于部分的解析,大家可以点击这里查看。
但是我们这里主要是想要看在,这个类中的一个函数。
def calculate(self):
s = self.line.text()
if len(s) == 0:
self.Text.setText(str(0))
return False
s = s.replace('^', '**') # 使得能够接受^这样的用法
try:
ans = eval(s) # 使用了eval
except:
return False
else:
self.Text.setText(str(ans))
看到了没有,在上面,通过使用这个快速实现了这个功能。想想自己以前用c++实现的时候,还有用一个大概50+行的简单算法实现。但是通过这个eval
函数,在这别压缩到只用一行。(当然啦,这个就涉及到Python这个函数的C代码实现的!)
不过在开发上确实变简单了很多。
我之前说到,我在看一段代码,就是值得这个源代码。
代码在这,用python2
from functools import partial as pto
from Tkinter import Tk, Button, X
from tkMessageBox import showinfo, showwarning, showerror
WARN = 'warn'
CRIT = 'crit'
REGU = 'regu'
SIGNS = {
'do not enter': CRIT,
'railroad crossing': REGU,
'55\n speed limit': REGU,
'wrong way': CRIT,
'merging traffic': WARN,
'one way': REGU,
}
critCB = lambda: showerror('Error', 'Error Button Pressed!')
warnCB = lambda: showwarning('Warning', 'Warning Button Pressed!')
infoCB = lambda: showinfo('Info', 'Info Button Pressed!')
top = Tk()
top.title('Road Signs')
Button(top, text='Quit', command=top.quit, bg='red', fg='white').pack()
MyButton = pto(Button, top)
CritButton = pto(MyButton, command=critCB, bg='white', fg='red')
WarnButton = pto(MyButton, command=warnCB, bg='goldenrod1')
ReguButton = pto(MyButton, command=infoCB, bg='white')
for eachSign in SIGNS:
signType = SIGNS[eachSign]
cmd = '%sButton(text=%r%s).pack(fill=X, expand=True)' % (
signType.title(), eachSign, '.upper()' if signType == CRIT else '.title()')
eval(cmd)
top.mainloop()
注意到,在这个代码的靠后面的几行代码,有这样的一个片段。
for eachSign in SIGNS:
signType = SIGNS[eachSign]
cmd = '%sButton(text=%r%s).pack(fill=X, expand=True)' % (
signType.title(), eachSign, '.upper()' if signType == CRIT else '.title()')
eval(cmd) # 使用eval
而在这里,我们使用了eval函数来输入代码。
可能大家第一个看到这代码,会想:这个玩意什么鬼??
哈哈哈这个确实很搞笑。我之前在Linux上用C++做过类似的功能都一下子楞到了。
我们这么说起。相信,用python的朋友,肯定都是用过命令行交互模式。或者说,那种交互模式才是一般非大程序开发使用的常态。(除非学习这个的人是程序员出身的….一般都会偏好命令行交互(有时候,会发现命令行交互确实实用,方便。))
可能大部分人的第一反映,都是会觉得我在这胡扯。如果是这个功能有什么用呢?我直接手写这个语句不就好了?为什么还要通过eval
这个函数来调用呢?
这里就涉及到了一个非常大胆的猜想
增加代码的复用性
这样的策略。object
这个类)。。这里,在python中引入的eval
作用就很可怕了。以前虽然能解决很多复用问题,但是有一类的问题没办法解决。
比如:
将下面的传转换成整数
A_str = '1'
B_str = '21'
C_str = '123'
这里只有三个,我们会想到的方法有,写三句话
A = int(A_str)
B = int(B_str)
C = int(C_str)
这还是由于python内植入了int这个函数的原因。要是没有,就需要自己再实现相关的代码了。总的来说,这里会特别复杂。
其实,就算只有三行类似这样的代码。我们敲起来都觉得很烦。这么重复的东西,为什么要我们自己手动敲代码?计算机才是最擅长干这种事情的呀??这种思想一直在程序员的圈子很受欢迎~
但,要是这里变成了100这个的变量呢?你会怎么处理?
这里,你可能会说,那我就不这样设置变量咯~然后封装成一个数组之类的东西,这样不就很好了么?
确实,其他很多语言都没有这个函数都还是能用,肯定是有这样的理由的。
但是,有必要强调的是,这样就会大大降低可读性质。(我们无法通过变量很快的得知对应的意思, 虽然大多数条件下,这个不影响,但是很多时候这个很有必要!)
比如我那使用的代码(虽然也可以使用手打
但是那样就会特别麻烦。
Python作为一门简洁的语言,怎么会让自己有这样的漏洞呢?(能解决的问题,最好就提前解决。
因为Python最受欢迎的一点,就是使用起来特别方便,特别容易上手~这点既然存在,那它就必须要去解决掉。
所以,就有了这个函数。
就是,通过这函数,实现了程序员内心深处最想要的工具,就是自动打码!
对,这个功能特别夸张,在这种基础下,很大程度上缩短了代码量。
因为,很多代码由于有类似的特征。就通过控制string的方式来进行控制代码,然后这样,就可以通过一个模板,让程序自动生成一系列相关的代码。
比如我用的第二代码!