學(xué)習(xí) Python 的第一節(jié)課不僅僅是 “Hello World”,相信也有“Python 之禪”。當(dāng)你在交互解釋器中輸入 import this 就會顯示 Tim Peters 的 The Zen of Python: >>>import thisThe Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! 在網(wǎng)上找了篇排名靠前的翻譯,發(fā)現(xiàn)不完整,還是谷歌翻譯湊合看吧: 美麗勝于丑陋。 顯式勝于隱式。 簡單勝于復(fù)雜。 復(fù)雜勝于復(fù)雜。 扁平比嵌套更好。 稀疏勝于密實(shí)。 可讀性很重要。 特殊情況還不足以打破規(guī)則。 盡管實(shí)用性勝過純度。 錯誤絕不能默默傳遞。 除非明確地保持沉默。 面對模棱兩可,拒絕猜測的誘惑。 應(yīng)該有一種-最好只有一種-明顯的方式來做到這一點(diǎn)。 盡管除非您是荷蘭人,否則一開始這種方式可能并不明顯。 現(xiàn)在總比沒有好。 盡管從來沒有什么比現(xiàn)在“正確”更好。 如果實(shí)現(xiàn)難以解釋,那是個壞主意。 如果實(shí)現(xiàn)易于解釋,則可能是個好主意。 命名空間是一個很棒的主意-讓我們做更多這些吧! 而在 Python 幾十年的發(fā)展過程中,禪被包裹了一層又一層,混雜了更多東西,最后出現(xiàn)了 Pythonic 這個新創(chuàng)的單詞,是 Python 之禪的解釋和體現(xiàn)。 就像 ComputerHope 網(wǎng)站解釋的那樣: Pythonic 是一個形容詞,它描述了一種與 Python 編程語言的創(chuàng)立哲學(xué)一致的計(jì)算機(jī)編程方法。在 Python 中有很多方法可以完成相同的任務(wù),但是通常有一種首選的方法可以完成此任務(wù)。這種首選方式稱為“Pythonic”。 但是這對于大家來說依然是一個籠統(tǒng)的概念,就像迷霧之中的燈塔,讓人看不清楚,就算有一天偶爾觸摸到了,你可能也意識不到。 只有直接通過 Python 的方法解決一個問題的時候,或許才會明悟。 try finally下面就說說我從try finally 到 with 中學(xué)到的 Pythonic: 2019年的時候,工作需要我接觸了 xlwings 這個 Python 庫,當(dāng)然我是使用的 Python2.7 版本。 簡單介紹一下該庫,不然下面講不下去,xlwings 庫是一個可以直接調(diào)用電腦上 Excel 的接口的庫,用戶可以通過 xlwings 新建 Excel 表格、修改、計(jì)算其中的數(shù)據(jù)等等。 不同于其他處理 Excel 表格的庫,由于 xlwings 是直接在后臺調(diào)用 Excel 程序來打開需要處理的表格,所以處理過程中,我在任務(wù)管理器中是可以看到一個 Excel 程序被啟動了。 當(dāng)然這沒有什么問題,xlwings 很強(qiáng)大,Excel 有的功能基本上都能調(diào)用,也沒有其它庫關(guān)于 xls、xlsx 這種弱智的文件版本問題,但是:在代碼運(yùn)行過程中報錯的話,后臺的 Excel 程序不會自動銷毀,而會變成僵尸程序,永遠(yuǎn)留在系統(tǒng)中除非人為干預(yù)刪除。 這就很搞笑了,留了一個 Excel 程序在后臺,打開任務(wù)管理器可以看到: 然后我試著重新打開那個 Excel 文件,會出錯,錯誤提示:在另一個應(yīng)用程序打開。請將其關(guān)閉,然后重試。 所以這個 Excel 文件直接就不能正常打開了,xlwings 當(dāng)然也不能打開這個表格了,因?yàn)檫@個表格已經(jīng)被后臺中的僵尸程序占用了,所以我只能在任務(wù)管理器中將 Excel 進(jìn)程關(guān)閉,然后才能繼續(xù)操作。 非常麻煩,代碼在編寫過程中運(yùn)行出錯是很常見的,難道每出錯一次就手動終止進(jìn)程一次? 所以使用 try - finally 語句塊,在 finally 語句下寫退出代碼,這樣就算是報錯還是怎么樣都是沒有問題的,程序都會退出(除非你連退出程序的代碼都寫錯了)。 這里還是放上示例代碼吧: # -*- coding:utf-8 -*-import xlwings as xw import os try: path = "test.xlsx" app1 = xw.App(visible=False, add_book=False) app1.display_alerts = False wb = app1.books.open(path) wb_sheet1 = wb.sheets[0] cell = wb_sheet1.range("A1") cell.nonono() cell.value = 2 wb.save() finally: app1.quit() 那么這就是 Pythonic 的寫法嘛?當(dāng)然不是,我從來不覺得加了 try- finally 就很優(yōu)雅了,因?yàn)橄?try-else-except-finally 這些是程序語言的錯誤處理機(jī)制,在很多語言中都存在,并且個人不是很喜歡設(shè)置過多的縮進(jìn)級別。 我只是為了能讓程序跑起來,先整上再說。 with而真正將其寫的比較 Pythonic 是幾個月后吧,應(yīng)該: 后來頻繁的使用 xlwings 來處理 Excel 表格,我想把涉及到的代碼模塊化,方便復(fù)用,可以就是由于這個煩人的 try-finally 語句塊導(dǎo)致讀取模塊化工作做不出來,因?yàn)?try 和 finally 是相連的,且finally 中就是程序退出代碼(可能我技術(shù)有限吧,先把這句話說出來,免得被噴)。 這怎么能行呢?思來想去,就像前面說的: “Pythonic 是一個形容詞,它描述了一種與 Python 編程語言的創(chuàng)立哲學(xué)一致的計(jì)算機(jī)編程方法” 我直接好家伙,使用上下文管理器不就行了嘛,一個 with 解決一切煩惱,這不就是保持與 Python 編程語言的創(chuàng)立哲學(xué)一致嘛! 使用上下文管理器就可以自動在程序結(jié)束后、或者出錯后,自動將后臺程序退出。并且只用 with 即可,上下文使用非常廣泛,比如 創(chuàng)建上下文管理器有兩種方式,一種是使用內(nèi)置方法 我使用的是第二種較為簡單的方法,名稱比較長:上下文管理器裝飾器;就像名字一樣,添加一個裝飾器再添加一個 yield 關(guān)鍵字就行了。 看看下面這個例子: # -*- coding:utf-8 -*-from contextlib import contextmanager import xlwings as xw @contextmanager def open_xlwings(input_file, output=None): app = xw.App(visible=False, add_book=False) app.display_alerts = False app.screen_updating = False print "input_file:", input_file wb = app.books.open(input_file) print "File Name: {}".format(app.books) print "Pid: {}".format(app.pid) sheet = wb.sheets[0] yield sheet # 返回 sheet print "Quit Xlwings" app.quit() 被裝飾器裝飾的函數(shù)分為三部分:
看看下面這個簡單例子及其輸出結(jié)果就明白了: import xlwings as xwimport os from glwings import open_xlwings path = "test.xlsx" with open_xlwings(path) as p: # code print "ok" 輸出結(jié)果 input_file: test.xlsxFile Name: Books([<Book [test.xlsx]>]) Pid: 11788 ok Quit Xlwings 但是這樣還是不行哦,如果 with 語句塊的代碼出錯的話,后續(xù)的也會直接停止的,所以在上下文管理器裝飾器所修飾的函數(shù)中需要加入錯誤處理模塊: # -*- coding:utf-8 -*-from contextlib import contextmanager import xlwings as xw @contextmanager def open_xlwings(input_file, output=None): app = xw.App(visible=False, add_book=False) app.display_alerts = False app.screen_updating = False print "input_file:", input_file wb = app.books.open(input_file) print "File Name: {}".format(app.books) print "Pid: {}".format(app.pid) sheet = wb.sheets[0] try: yield sheet # 返回 sheet except Exception as e: info = "with an error {}".format(e) raise else: if output: wb.save(output) else: wb.save() finally: print "Quit Xlwings" app.quit() 還是非常簡單的,現(xiàn)在就可以非常安心的使用 with 語句來操控 xlwings 打開 Excel 表格了。 其實(shí)像這種功能 xlwings 庫應(yīng)該自己就需要實(shí)現(xiàn)的,不知道為什么沒有支持 with 的文件對象,當(dāng)然咯我說的是對應(yīng) Python2.7 版本的 xlwings,像現(xiàn)在最新的 Python3 版本對應(yīng) xlwings 怎么樣了我就不清楚了,不過多半沒什么變化,如果能支持早就支持了,不會等到現(xiàn)在。 如果以后有人問你,什么是 Pythonic,你叫他多寫 with 就可以了,這就是一種 Pythonic 的寫法,非常的純正,非常的 Pythonic;而編寫5、6層嵌套的簡直是在犯罪。 優(yōu)美(美麗)是Python 之禪的第一個詞,這就是我理解的 Pythonic。 這是一篇半心得體會半技術(shù)的文章,心得體會部分充斥了本人的主觀臆斷,不可全?。患夹g(shù)部分可以小心參考。 |
|