【干货】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 QCoreApplicationclass 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 Falses = s.replace('^', '**') # 使得能夠接受^這樣的用法try:ans = eval(s)except:return Falseelse: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 Falses = s.replace('^', '**') # 使得能夠接受^這樣的用法try:ans = eval(s) # 使用了evalexcept:return Falseelse: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, showerrorWARN = '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 = int(A_str) B = int(B_str) C = int(C_str)這還是由于python內植入了int這個函數的原因。要是沒有,就需要自己再實現相關的代碼了。總的來說,這里會特別復雜。
其實,就算只有三行類似這樣的代碼。我們敲起來都覺得很煩。這么重復的東西,為什么要我們自己手動敲代碼?計算機才是最擅長干這種事情的呀??這種思想一直在程序員的圈子很受歡迎~
但,要是這里變成了100這個的變量呢?你會怎么處理?
這里,你可能會說,那我就不這樣設置變量咯~然后封裝成一個數組之類的東西,這樣不就很好了么?
確實,其他很多語言都沒有這個函數都還是能用,肯定是有這樣的理由的。
但是,有必要強調的是,這樣就會大大降低可讀性質。(我們無法通過變量很快的得知對應的意思, 雖然大多數條件下,這個不影響,但是很多時候這個很有必要!)
比如我那使用的代碼(雖然也可以使用手打
但是那樣就會特別麻煩。
Python作為一門簡潔的語言,怎么會讓自己有這樣的漏洞呢?(能解決的問題,最好就提前解決。
因為Python最受歡迎的一點,就是使用起來特別方便,特別容易上手~這點既然存在,那它就必須要去解決掉。
所以,就有了這個函數。
這個函數最大的功能!
就是,通過這函數,實現了程序員內心深處最想要的工具,就是自動打碼!
對,這個功能特別夸張,在這種基礎下,很大程度上縮短了代碼量。
因為,很多代碼由于有類似的特征。就通過控制string的方式來進行控制代碼,然后這樣,就可以通過一個模板,讓程序自動生成一系列相關的代碼。
比如我用的第二代碼!
總結
以上是生活随笔為你收集整理的【干货】eval函数用法解释及对开发者的便利讲解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [解析]多线程加锁Lock调用pytho
- 下一篇: 【干货】Dask快速搭建分布式集群(大数