2017年2月21日 星期二

TAB 縮排 空白????

學python 到現在最有困擾的一個非程式原理的地方就是縮排.....。
python開宗明義就說,python用縮排來做為區隔有助於簡潔程式碼.......blah blah......
這就變成一個很有趣的問題,到底縮排是什麼?????
首先縮排只是一個閱讀或是文字排版上的一個方式,目的在幫助人們閱讀或是更了解文字結構以及表達意思。如果你去看很多古籍,圖書館的四庫全書翻一下你會發現,他們是沒有在縮排的。所以因為古籍沒有縮排又沒有逗點也就產生了另一個衍生著作叫做集注(題外話)。甚至如果去翻像是美國獨立宣言以及英國大憲章,就是看到一句一句接著寫。如果以現在的眼光來看就是很難讀。而我們現在都很清楚,標點與縮排對於文意有時候會產生相當大的影響。於是這也變成了一門藝術與學問,排版。

講完這些你就會發現一件事情,縮排是一種空間視覺感,在一定空間上進行的文字結構排列處理方式。所以他本身其實並沒有一個硬性規定,只有看起來舒服不舒服的問題。所以如果回過頭去看python就變成了一個有趣的現象。五個設計師加上五個編輯器他們的縮排可能有好多種。而在程式碼整合與搬家的時候就變成很痛苦的事情。同樣的問題在C身上就沒有,C用大括號{}來處理巢狀結構問題。所以即便五個程式設計師加上五個編輯器。但是在搬家的時候不管某個人縮排縮得多爛,在整合上就是數括號而已......,在電腦讀起來他是沒有也不會覺得寫程式的人有沒有排版藝術與美感的,他只是單純地處理文字代碼而已。但是在python上這就變成了問題,因為它直接影響巢狀結構......於是就會變成你的縮排可能不是我的縮排,你這邊縮了兩次可能我這邊眼睛看起來只有一次。

因為python適用縮排來處理程式結構,而python又對縮排方式沒有硬性規定,於是就是很多有趣的現象,EX:^I 字元在VIM是標準的縮排符號,如果你在sublime上面用這個編輯,然後寫好的程式給很多人用,那每一個人的電腦打開來看原始碼,會看見各種不同長短的縮排間距,然後如果今天兩個程式要整合,縮排間距不同彼此貼上去......哇那改就改死人了。

所以根據PEP (Python Enhancement Purposal) 8 號文件
Never mix tabs and spaces.
The most popular way of indenting Python is with spaces only. The second-most popular way is with tabs only. Code indented with a mixture of tabs and spaces should be converted to using spaces exclusively. When invoking the Python command line interpreter with the -t option, it issues warnings about code that illegally mixes tabs and spaces. When using -tt these warnings become errors. These options are highly recommended!
For new projects, spaces-only are strongly recommended over tabs. Most editors have features that make this easy to do.
就是說:
絕對不要把跳格和空白混在一起。
對 Python 進行縮排時,最常見的方式是僅使用空白,其次是只用跳格。把跳格和空白混在一起的程式碼,應該要把跳格轉換成空白。如果在呼叫 Python 直譯器的時候加上 -t 參數,混用跳格和空白的程式會使直譯器發出警告。如果用了 -tt 參數,則會發出錯誤。建議使用這些參數!
若進行新專案時,強烈建議採用僅用空白的縮排方式,不要用跳格。很多編輯器都具備自動轉換能力。
定義一個縮排方式是有必要的,目前根據文件內容以及台灣pycon掌門人的意見:

在用 Python 開發新專案的時候,用不多不少恰恰好是 4 個空白字元進行縮排,不讓程式裡出現任何跳格字元,會是最容易和別人一起合作寫 Python 的習慣。Python 標準程式庫裡大都如此縮排,其它新開發的 Python 專案也這樣縮排,所以如果我們也這樣作,我們不必費力去習慣其它人的縮排慣例,別人在看我們的程式時也可以省心。因此,我建議剛開始學習 Python 程式設計的新手,如果還沒有養成任何縮排習慣的話,
固定用四個空白字元進行縮排
而在vim 裡面設計良好的縮排環境如下:

:set autoindent(ai) 自動縮排功能,就是我這一行如果進行縮排,那我換行的時候也會做同樣的縮排
:set expandtab(et) 用空白符號取代跳格符號,按了tab後,他就會跳一定數量的空白符號,而不是^I
:set shiftwidth(sw)=4 整行移動時的寬度
:set tabstop(ts)=4  tab的寬度(這裡是寬度喔不是字元數)

P.S. 1:有些會建議加上set softtabstop=4,根據經驗加不加沒有影響到什麼,所以依據奧卡姆剃刀原則,如無必要勿增實體,我就沒加這個了。

P.S. 2:,大家來學VIM的作者說,如果會要寫makefile之類的,這個就不要亂改,如果會需要用到原有的tab就用,ctrl+v+tab 或是ctrl+v+I就好


這四個動作的意思就是自動縮排,然後tab用空白取代,tab寬度是4個字元的寬度

最後如果要整合別人的程式怎麼辦?介紹一個比較方便的程式碼整理工具,autopep8。
顧名思義就是它會自動地把你的程式碼按照PEP8的要求格式進行整理編排。詳細安裝與使用就不說明了,直接看結果。

我們利用劉人維的程式來做案例


左邊是在我這邊看到的,右邊是實際上的代碼,每一個tab (^I)都變成八個空格。如果我今天想要複製他的函式到我的程式碼上,因為縮排規格不同就會出現執行錯誤。

如果今天程式碼有幾百行,那改這個縮排就會改死人,現在我們使用autopep8
可以看到原有的程式碼被整理過,左邊是在我這邊看到的,右邊縮排的規則被更改了。程式碼也經過整理


正常模式,看起來也舒服多了。

小問題的解決也花了不少功夫,給大家做個參考。

1 則留言: