不管你是待業(yè)還是失業(yè),在這個(gè)被互聯(lián)網(wǎng)圍繞的時(shí)代里,選擇用python計算,就多了一項技能,還怕找不到工作?,還怕不好找工作?小編就來(lái)告訴你這個(gè)專(zhuān)業(yè)的優(yōu)勢到底體現在哪里:Python 多核并行計算,Python入門(mén)到精通(2):使用Python計算數學(xué)算式,python并行計算(完結篇):并行方法總結,python計算360.65+239.2為什么會(huì )出現好多9,python計算兩個(gè)時(shí)間戳相差多少秒,用Python寫(xiě)個(gè)計算器??。
1.Python 多核并行計算
以前寫(xiě)點(diǎn)小程序其實(shí)根本不在乎并行,單核跑跑也沒(méi)什么問(wèn)題,而且我的電腦也只有雙核四個(gè)超線(xiàn)程(下面就統稱(chēng)核好了),覺(jué)得去折騰并行沒(méi)啥意義(除非在做IO密集型任務(wù))。然后自從用上了32核128GB內存,看到 htop 里面一堆空載的核,很自然地就會(huì )想這個(gè)并行必須去折騰一下。后面發(fā)現,其實(shí) Python 的并行真的非常簡(jiǎn)單。 vs 自帶的庫又全又好用,這是我特別喜歡 Python 的原因之一。Python 里面有 和 threading 這兩個(gè)用來(lái)實(shí)現并行的庫。用線(xiàn)程應該是很自然的想法,畢竟(直覺(jué)上)開(kāi)銷(xiāo)小,還有共享內存的福利,而且在其他語(yǔ)言里面線(xiàn)程用的確實(shí)是非常頻繁。然而,我可以很負責任的說(shuō),如果你用的是 CPython 實(shí)現,那么用了 threading 就等同于和并行計算說(shuō)再見(jiàn)了(實(shí)際上,甚至會(huì )比單線(xiàn)程更慢),除非這是個(gè)IO密集型的任務(wù)。 指的是 python.org 提供的 Python 實(shí)現。是的,Python 是一門(mén)語(yǔ)言,它有各種不同的實(shí)現,比如 PyPy, Jython, 等等……我們用的最多的就是 CPython,它幾乎就和 Python 畫(huà)上了等號。CPython 的實(shí)現中,使用了 GIL 即全局鎖,來(lái)簡(jiǎn)化解釋器的實(shí)現,使得解釋器每次只執行一個(gè)線(xiàn)程中的字節碼。也就是說(shuō),除非是在等待IO操作,否則 CPython 的多線(xiàn)程就是徹底的謊言!有關(guān) GIL 下面兩個(gè)資料寫(xiě)的挺好的:Python的GIL是什么鬼,多線(xiàn)程性能究竟如何 the Python .Pool因為 GIL 的緣故 threading 不能用,那么我們就好好研究研究 。(當然,如果你說(shuō)你不用 CPython,沒(méi)有 GIL 的問(wèn)題,那也是極佳的。)首先介紹一個(gè)簡(jiǎn)單粗暴,非常實(shí)用的工具,就是 .Pool。如果你的任務(wù)能用 ys = map(f, xs) 來(lái)解決,大家可能都知道,這樣的形式天生就是最容易并行的,那么在 Python 里面并行計算這個(gè)任務(wù)真是再簡(jiǎn)單不過(guò)了。舉個(gè)例子,把每個(gè)數都平方:import def f(x): return x * x cores = .cpu_count() pool = .Pool(processes=cores) xs = range(5) # method 1: map print pool.map(f, xs) # prints [0, 1, 4, 9, 16] # method 2: imap for y in pool.imap(f, xs): print y # 0, 1, 4, 9, 16, # method 3: imap_unordered for y in pool.imap_unordered(f, xs): print(y) # may be in any order map 直接返回列表,而 i 開(kāi)頭的兩個(gè)函數返回的是迭代器;imap_unordered 返回的是無(wú)序的。當計算時(shí)間比較長(cháng)的時(shí)候,我們可能想要加上一個(gè)進(jìn)度條,這個(gè)時(shí)候 i 系列的好處就體現出來(lái)了。另外,有一個(gè)小技巧,就是輸出 \r 可以使得光標回到行首而不換行,這樣就可以制作簡(jiǎn)易的進(jìn)度條了。cnt = 0 for _ in pool.imap_unordered(f, xs): sys.stdout.write('done %d/%d\r' % (cnt, len(xs))) cnt += 1 更復雜的操作要進(jìn)行更復雜的操作,可以直接使用 .Process 對象。要在進(jìn)程間通信可以使用:..Queue同步原語(yǔ)共享變量其中我強烈推薦的就是 Queue,因為其實(shí)很多場(chǎng)景就是生產(chǎn)者消費者模型,這個(gè)時(shí)候用 Queue 就解決問(wèn)題了。用的方法也很簡(jiǎn)單,現在父進(jìn)程創(chuàng )建 Queue,然后把它當做 args 或者 kwargs 傳給 Process 就好了。使用 Theano 或者 等工具時(shí)的注意事項需要注意的是,在 import theano 或者 import 等調用了 Cuda 的工具的時(shí)候會(huì )產(chǎn)生一些副作用,這些副作用會(huì )原樣拷貝到子進(jìn)程中,然后就發(fā)生錯誤,如:could not retrieve CUDA device count: CUDA_ERROR_NOT_ 解決的方法是,保證父進(jìn)程不引入這些工具,而是在子進(jìn)程創(chuàng )建好了以后,讓子進(jìn)程各自引入。如果使用 Process,那就在 target 函數里面 import。舉個(gè)例子:import def hello(taskq, resultq): import as tf config = tf.() config.gpu_options.allow_growth=True sess = tf.Session(config=config) while True: name = taskq.get() res = sess.run(tf.constant('hello ' + name)) resultq.put(res) if __name__ == '__main__': taskq = .Queue() resultq = .Queue() p = .Process(target=hello, args=(taskq, resultq)) p.start() taskq.put('world') taskq.put('') taskq.close() print(resultq.get()) print(resultq.get()) p.terminate() p.join() 如果使用 Pool,那么可以編寫(xiě)一個(gè)函數,在這個(gè)函數里面 import,并且把這個(gè)函數作為 傳入到 Pool 的構造函數里面。舉個(gè)例子:import def init(): global tf global sess import as tf config = tf.() config.gpu_options.allow_growth=True sess = tf.Session(config=config) def hello(name): return sess.run(tf.constant('hello ' + name)) if __name__ == '__main__': pool = .Pool(processes=2, =init) xs = ['world', '', 'Lequn Chen'] print pool.map(hello, xs) ?首發(fā)于博客 Python 多核并行計算
2.Python入門(mén)到精通(2):使用Python計算數學(xué)算式
重點(diǎn)學(xué)習Python算式表達式和算術(shù)運算符,通過(guò)Shell窗口完成簡(jiǎn)單的數學(xué)運算1、 算術(shù)表達式在Pyhton語(yǔ)言中,數學(xué)算式中的小數或整數稱(chēng)為數值,數學(xué)算式稱(chēng)為算術(shù)表達式。算式中的數值稱(chēng)為操作數,算式中的運算符號稱(chēng)為運算符。在算術(shù)表達式中,算式的數值稱(chēng)為操作數,算式的運算符號稱(chēng)為運算符。在一些復雜的運算中,簡(jiǎn)單的表達式可以組合為復雜的表達式,其操作數本身可能就是一個(gè)表達式。算術(shù)表達式的計算結果為數值。例如上圖表達式運算符“+”兩邊的操作數是(12+9)和(20/5),它們本身就是一個(gè)表達式。2、 算術(shù)運算符下面的表格對算術(shù)表達式使用到的運算符和數學(xué)算式中的運算符號進(jìn)行了比較,這樣就可以借助數學(xué)算式的運算符號來(lái)理解算術(shù)表達式的運算符。在算術(shù)運算符表格中,加減乘除運算符已經(jīng)比較熟悉了。下面介紹取模運算符“%”、冪運算運算符“**”和取整除“//”運算符。取模運算符“%”用于取模運算,取模運算和數學(xué)中的取余運算是一樣的,運算結果返回兩個(gè)數值相除后的余數。上機操作:首先計算163除以7,163除以7的商是23余數是2。然后在IDLE的Shell窗口輸入算術(shù)表達式“163 % 7”,按下電腦鍵盤(pán)的【Enter】鍵,Shell窗口執行輸入的算術(shù)表達式并輸出結果2?!?5 % 5”的運算結果是多少呢?15除以5的余數是0。如果兩數相除的余數是0,那么這兩個(gè)數取模運算的結果是多少呢?上機操作:在Shell窗口輸入“15 % 5”,Shell窗口執行算式,并輸出結果0。冪運算符“**”用于數值的乘方運算,乘方運算是指一個(gè)數連續自乘n次,可以稱(chēng)為該數的n次乘方。例如:3個(gè)5連續自乘,可以稱(chēng)為3的5次乘方。除0外,任何數的0次乘方都為1。乘方運算的結果稱(chēng)為冪,因此乘方運算也稱(chēng)為冪運算。冪運算符“**”有兩個(gè)操作數,運算符左邊的操作數是乘方的底數,運算符右邊的操作數是乘方的指數。例如:計算2的3次方,算術(shù)表達式可以這么寫(xiě)“2**3”,2是底數,3是指數。上機操作:在Shell窗口輸入了算術(shù)表達式“2**3”,Shell窗口輸出計算結果8。使用冪運算符時(shí),運算符左側的數值是乘方運算的底數,運算符右側的數值是乘方運算的指數。取整除運算符“//”用于兩數除法取商的整數部分,也就是運算結果返回兩數相除后商的整數部分,商的小數部分及余數忽略。例如:19除以2的取整除運算結果是9。取整除運算符“//”有兩個(gè)操作數,運算符左邊的操作數是被除數,運算符右邊的操作數是除數。上機操作:在Shell窗口輸入算術(shù)表達式“19 // 2”,Shell窗口輸出計算結果9。在輸入“//”運算符時(shí)要注意和除法運算符“/”的區別,除法運算符是一個(gè)“/”符號,取整除是兩個(gè)“//”符號。了解了算術(shù)運算符,做下面的練習!在上機練習前,先介紹一下練習的操作步驟:(1)首先啟動(dòng)IDLE開(kāi)發(fā)工具,Shell窗口被打開(kāi)。(2)在Shell窗口的命令提示符“>>>”的光標處輸入算術(shù)表達式,算術(shù)表達式輸入完成后,按下電腦鍵盤(pán)【Enter】鍵,Shell窗口會(huì )執行剛才輸入的算術(shù)表達式,并在算術(shù)表達式的下面一行,輸出算術(shù)表達式的計算結果。在Shell窗口輸入上面的算式,每輸入完成一個(gè)算式,就按下電腦鍵盤(pán)的【Enter】鍵執行該算式。>>> 21+79-3268>>> 28+120*8988>>> (45+16)/4*23350.75>>> 3**327>>> 19 % 61>>> 21 // 63>>>初學(xué)Python的同學(xué)在輸入算術(shù)表達式時(shí),可能會(huì )在輸入法的中文模式下輸入,如果在中文模式下輸入,可能會(huì )導致算術(shù)表達式的語(yǔ)法錯誤。上面的錯誤就是在輸入算式時(shí),在中文模式下輸入了小括號“(”,Shell窗口會(huì )輸出“語(yǔ)法錯誤:標識符中的字符無(wú)效”錯誤。3、 運算符的優(yōu)先級算術(shù)運算符的優(yōu)先級同四則運算的優(yōu)先級相同,下表給出了算術(shù)運算符的優(yōu)先級,表中優(yōu)先級的數字越小,優(yōu)先級越高。優(yōu)先級的結合性是指當一個(gè)表達式包含優(yōu)先級相同的運算符時(shí),表達式是從左到右順序運算,還是從右到左順序運算。4、 上機操作請同學(xué)們先用筆算計算下面的算術(shù)表達式,然后在用Python驗證算術(shù)表達式的計算結果是否正確。(1)0.94*2.6-0.9*2.6(2)3**2//3+(12-5)(3)6/3+10//3**2編程訓練營(yíng)APP創(chuàng )新在線(xiàn)學(xué)習模式,學(xué)習編程不再半途而廢安卓手機應用商店搜索編程訓練營(yíng)下載
3.python并行計算(完結篇):并行方法總結
由于python相當易學(xué)易用,現在python也較多地用于有大量的計算需求的任務(wù)。本文介紹幾個(gè)并行模塊,以及實(shí)現程序并行的入門(mén)技術(shù)。本文比較枯燥,主要是為后面上工程實(shí)例做鋪墊。完結篇對前期介紹的所有模塊及實(shí)例進(jìn)行總結,比較各并行方法的特點(diǎn)和異同。所有比較都以文字形式呈現了,歡迎指正或完善,做成表格可能效果更好。模塊介紹:愛(ài)coding:python并行計算(上):、模塊愛(ài)coding:python并行計算(上):pathos模塊愛(ài)coding:python并行計算(上):.futures、pp模塊實(shí)例:愛(ài)coding:python并行計算(下):模塊實(shí)例愛(ài)coding:python并行計算(下):pathos模塊實(shí)例愛(ài)coding:python并行計算(下):.futures、pp模塊實(shí)例注:以下模塊、類(lèi)與其他內容相同或接近,不重復介紹和比較:模塊:與模塊接口基本一致。pathos.pp.pp模塊:實(shí)質(zhì)也即pp模塊,與獨立的pp模塊完全相同。pathos..Pool():與.Pool()完全相同。pathos..()、pathos.pools.():與pathos..()完全相同。pathos.pp.()、pathos.parallel.()、pathos.parallel.()、pathos.pools.():與pathos.pp.()完全相同。pathos.serial.():實(shí)際是串行(非并行),不參與比較。1、按并行分類(lèi)(1)阻塞(非并行):非并行方式下,子進(jìn)程串行執行(完成一個(gè),然后開(kāi)始下一個(gè)),實(shí)際不是并行。包括:.Pool(),apply方法pathos..(),pipe方法pathos.pp.(),pipe方法pathos.pp.(),map方法pathos.pp.(),imap方法(2)批次并行:批次并行指一批子進(jìn)程并行執行,且直到該批次所有子進(jìn)程完成后,才開(kāi)始下一批次。包括:.Process() #只能一批一批地添加進(jìn)程,同一批次內并行(3)異步:異步執行指的是一批子進(jìn)程并行執行,且子進(jìn)程完成一個(gè),就新開(kāi)始一個(gè),而不必等待同一批其他進(jìn)程完成。包括:.Pool(),apply_async方法.Pool(),map方法.Pool(),map_async方法.Pool(),imap方法.Pool(),imap_unordered方法.Pool(),starmap方法.Pool(),starmap_async方法.futures.(),submit方法.futures.(),map方法pathos..(),map方法pathos..(),imap方法pathos..(),uimap方法pathos..(),amap方法pathos..(),apipe方法pp.Server(),submit方法pathos.pp.(),apipe方法pathos.pp.(),amap方法pathos.pp.(),uimap方法2、按傳參分類(lèi)(1)單個(gè)任務(wù),任務(wù)多參數:.Process().futures.(),submit方法.Pool(),apply方法.Pool(),apply_async方法pathos..(),pipe方法pathos..(),apipe方法pp.Server(),submit方法pathos.pp.(),pipe方法pathos.pp.(),apipe方法(2)多個(gè)任務(wù),任務(wù)單參數:.Pool(),map方法.Pool(),map_async方法.Pool(),imap方法.Pool(),imap_unordered方法(3)多個(gè)任務(wù),任務(wù)多參數:(a)func(iterable[i])形式:iterable的每個(gè)元素(元素本身也是iterable)對應func的多個(gè)參數。.Pool(),starmap方法.Pool(),starmap_async方法(b)func(iterable1[i], iterable2[i], ...)形式:每個(gè)iterable對應func的一個(gè)參數。.futures.(),map方法pathos..(),map方法pathos..(),imap方法pathos..(),uimap方法pathos..(),amap方法pathos.pp.(),map方法pathos.pp.(),amap方法pathos.pp.(),imap方法pathos.pp.(),uimap方法3、按返回分類(lèi)(1)返回任務(wù)返回值.Pool(),apply方法pathos..(),pipe方法pathos.pp.(),pipe方法(2)返回.Pool(),map方法.Pool(),starmap方法pathos..(),map方法pathos.pp.(),map方法(3)返回返回MapResult或實(shí)例,通過(guò)get方法獲取返回值。需要注意的是:由于每個(gè)實(shí)例對應單個(gè)子進(jìn)程,其get方法本身是阻塞的,因此,在進(jìn)程添加過(guò)程中不可包含get方法,而應在所有進(jìn)程完成后,再一起調用get方法。對于MapResult不存在該問(wèn)題,因為所有子進(jìn)程只會(huì )一起返回一個(gè)MapResult實(shí)例。包括:.Pool(),apply_async方法pathos..(),apipe方法pathos.pp.(),apipe方法(4)返回.Pool(),map_async方法.Pool(),starmap_async方法pathos..(),amap方法pathos.pp.(),amap方法(5)返回迭代器或生成器迭代器/生成器對內存的需求會(huì )小得多,但速度比普通方法要慢很多(未驗證)。不過(guò),對于本文的小型任務(wù),看不出差別。(a)按順序:即按任務(wù)添加順利返回。.Pool(),imap方法.futures.(),map方法pathos..(),imap方法pathos.pp.(),imap方法(b)不按順序:實(shí)際按任務(wù)完成順序返回。.Pool(),imap_unordered方法pathos..(),uimap方法pathos.pp.(),uimap方法(6)無(wú)直接返回值.Process() #無(wú)直接返回值,可通過(guò)進(jìn)程間通信的方式返回任務(wù)返回值。.futures.(),submit方法 #future對象可以通過(guò)result方法獲取子進(jìn)程任務(wù)返回值。但該方法是阻塞的,因此,應在所有子進(jìn)程完成后再調用。pp.Server(),submit方法 #Task對象可調用(即Task()),調用可返回任務(wù)返回值。但調用是阻塞的,因此,應在所有子進(jìn)程完成后再調用。
4.python計算360.65+239.2為什么會(huì )出現好多9
深層原因是在于計算機無(wú)法精確表示部分浮點(diǎn)數時(shí),只能近似表示,因此存在誤差,這是所有編程語(yǔ)言都存在的問(wèn)題,可深入了解下,這種問(wèn)題無(wú)法徹底解決; 常見(jiàn)的應對辦法是在制定的精度要求下,乘法-》截取-》除法,如 0.1 + 0.2 = 0. (保留1位小數)int(0. *10 ) /10,截取方法也有很多可了解下;
5.python計算兩個(gè)時(shí)間戳相差多少秒
在Python編程中,使用datetime模塊計算兩個(gè)時(shí)間的差:>>> import datetime>>> d1=datetime.datetime(2015,7,5)>>> d2=datetime.datetime(2005,7,4)>>>(d1-d2).seconds//結果86400s# 計算兩個(gè)時(shí)間的間隔天數# 注意:輸入月份和天時(shí),不能輸入08,09等,會(huì )被識別為 8 進(jìn)制而出錯?。?進(jìn)制是不超過(guò)07的)# 解決辦法:要把月份和天前面的0去掉。
6.用Python寫(xiě)個(gè)計算器
我們常見(jiàn)的計算輔助工具有兩種,一種是古人發(fā)明的算盤(pán),另一種就是我們現代人發(fā)明的計算器,與算盤(pán)相比,計算器無(wú)論是便利性還是計算速度都是優(yōu)于算盤(pán)的,本文我們使用 Python 來(lái)實(shí)現一個(gè)簡(jiǎn)易的計算器。實(shí)現我們幾乎每個(gè)人都用過(guò)計算器,大家對于計算器應該都是比較熟悉的,計算器整體也是比較簡(jiǎn)單的,主要包括:顯示器、鍵盤(pán)、運算的邏輯處理等,計算器的圖形界面我們使用 tkinter 庫實(shí)現,下面看一下具體實(shí)現過(guò)程。首先,我們畫(huà)一個(gè)主窗口,代碼實(shí)現如下:# 創(chuàng )建主窗口 tk = tkinter.Tk() # 設置窗口大小和位置 tk.geometry('300x210+500+200') # 不允許改變窗口大小 tk.resizable(False, False) # 設置窗口標題 tk.title('計算器')看一下效果:我們接著(zhù)畫(huà)顯示器,代碼實(shí)現如下:# 自動(dòng)刷新字符串變量,可用 set 和 get 方法進(jìn)行傳值和取值 = tkinter.StringVar(tk, '') # 創(chuàng )建單行文本框 = tkinter.Entry(tk, =) # 設置文本框為只讀 ['state'] = 'readonly' # 設置文本框坐標及寬高 .place(x=20, y=10, width=260, height=30)看一下效果:再接著(zhù)畫(huà)鍵盤(pán),代碼實(shí)現如下:# 按鈕顯示內容 bvalue = ['C', '+', '-', '//', '2', '0', '1', '√', '3', '4', '5', '*', '6', '7', '8', '.', '9', '/', '**', '='] index = 0 # 將按鈕進(jìn)行 5x4 放置 for row in range(5): for col in range(4): d = bvalue[index] index += 1 btnDigit = tkinter.Button(tk, text=d, command=lambda x=d: onclick(x)) btnDigit.place(x=20 + col * 70, y=50 + row * 30, width=50, height=20)看一下效果:界面畫(huà)完了,我們看一下處理運算邏輯的代碼,如下所示:# 點(diǎn)擊事件 def onclick(btn): # 運算符 operation = ('+', '-', '*', '/', '**', '//') # 獲取文本框中的內容 content = .get() # 如果已有內容是以小數點(diǎn)開(kāi)頭的,在前面加 0 if content.('.'): content = '0' + content # 字符串可以直接用+來(lái)增加字符 # 根據不同的按鈕作出不同的反應 if btn in '': # 按下 0-9 在 content 中追加 content += btn elif btn == '.': # 將 content 從 +-*/ 這些字符的地方分割開(kāi)來(lái) lastPart = re.split(r'\+|-|\*|/', content)[-1] if '.' in lastPart: # 信息提示對話(huà)框 tkinter..showerror('錯誤', '重復出現的小數點(diǎn)') return else: content += btn elif btn == 'C': # 清除文本框 content = '' elif btn == '=': try: # 對輸入的表達式求值 content = str(eval(content)) except: tkinter..showerror('錯誤', '表達式有誤') return elif btn in operation: if content.endswith(operation): tkinter..showerror('錯誤', '不允許存在連續運算符') return content += btn elif btn == '√': # 從 . 處分割存入 n,n 是一個(gè)列表 n = content.split('.') # 如果列表中所有的都是數字,就是為了檢查表達式是不是正確的 if all(map(lambda x: x.isdigit(), n)): content = eval(content) ** 0.5 else: tkinter..showerror('錯誤', '表達式錯誤') return # 將結果顯示到文本框中 .set(content)整體實(shí)現完了之后,我們來(lái)演示一下,看一下效果:是不是有內味了。打包為了更加方便的使用,我們可以將 Python 代碼打包成 exe 文件,打包我們使用 ,安裝用 pip install 命令即可。打包時(shí)我們使用 --onefile -- counter.py 命令即可,此時(shí)打包生成的文件是使用的默認圖標,如果我們想指定自己的圖標可以添加參數 --icon="xxx\xxx.ico",打包生成的文件在 dist 目錄,如下圖所示:此時(shí),我們直接運行 exe 文件就行了。用 Python 寫(xiě)個(gè)計算器本文非首發(fā)于個(gè)人號
就拿大數據說(shuō)話(huà),優(yōu)勢一目了然,從事IT行業(yè),打開(kāi)IT行業(yè)的新大門(mén),找到適合自己的培訓機構,進(jìn)行專(zhuān)業(yè)和系統的學(xué)習。