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