首页 > 程序开发 > 软件开发 > 其他 >

【干货】eval函数用法解释及对开发者的便利讲解

2018-03-10

【干货】eval函数用法解释及对开发者的便利讲解。Python中,默认有个函数名为eval。这个函数在诸多像我一样的菜鸡圈子里,是很少用的。我也一直以为这个没什么特别大的作用。直到今天,我在读一个源代码的时候,突然意识到这个函数的用途。

【干货】eval函数用法解释及对开发者的便利讲解。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代码实现的!)

不过在开发上确实变简单了很多。

第二个程序,Tk加上偏函数,实现简单实用。

我之前说到,我在看一段代码,就是值得这个源代码。

代码在这,用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++做过类似的功能都一下子楞到了。

这里,eval开始执行代码了。

我们这么说起。相信,用python的朋友,肯定都是用过命令行交互模式。或者说,那种交互模式才是一般非大程序开发使用的常态。(除非学习这个的人是程序员出身的….一般都会偏好命令行交互(有时候,会发现命令行交互确实实用,方便。))

经过观察,还有查资料。我们可以理解这个eval。就是在之前的代码执行的基础上,开始执行一个新的代码。

可能大部分人的第一反映,都是会觉得我在这胡扯。如果是这个功能有什么用呢?我直接手写这个语句不就好了?为什么还要通过eval这个函数来调用呢?

这里就涉及到了一个非常大胆的猜想

想我们编程过程中,经常会遇到要编写大量的重复,或者是相近的代码。这里,从代码出现开始,教授们,大神们,给我们的推荐就是诸如,增加代码的复用性这样的策略。 具体的实现呢,就会映射出一大批的技术手段。比如: 函数式编程:通过将复用的手段变成函数封装起来。然后每次调用的时候,就只需要改特定的参数了。 面向对象编程:封装成一个个类。这里不仅是增加了诸多方法(如,函数)的复用性。同时由于封装为一个整体,很大程度上提高了数据的复用性。(这里比如:我要设置一个关于人的变量,我可能就需要身高,性别等很多很多的信息。这每个特征都需要设置为一个int,或者string类型。这样你开法的程序没过多久就会把所有的你可能会想到的变量名全都使用完,或者是大幅度地增加变量名的长度。这里想到我的大学同学,一个学医学的,他们上课一个单词有高达 40(左右)个英语字母,这样的情况肯定是会加大开发的难度的。) 面向对象编程(多态,继承):这个也大幅度增加了复用性。这个主要体现在使用构造类上的轻松。同时,python这个语言就是一个非常好的通过这个技术开发出来的语言。(所有函数,变量,类都基于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的方式来进行控制代码,然后这样,就可以通过一个模板,让程序自动生成一系列相关的代码。
比如我用的第二代码!

相关文章
最新文章
热点推荐