在這個系列筆記中,我將陸續整理自己在學習 Python 程式語言及其框架的過程中留下的筆記和程式碼,目的是掌握如何在生產環境中利用各種領域的第三方框架來快速開發應用程式。和大多數學習過程一樣,我需要在第一部分筆記中花費一點篇幅來鳥瞰一下 Python 語言所涉及的領域,以便從全域性視野來規劃接下來的學習路線圖,為此,我會在https://github.com/owlman/study_note
專案的Programming/LanguageStudy/Python
目錄下建立一個名為的RouteMap
目錄,用於存放並維護接下來的這一部分筆記。
誠如大家所知,Python 是當前在程式設計領域中最為熱門的、解釋型的高階程式語言之一。它支援函數式、指令式、結構化和物件導向程式設計等多種程式設計範型,且擁有強大的動態型別系統和垃圾回收功能,能夠自動管理記憶體使用,並且其本身擁有一個巨大而廣泛的標準庫。這些特性可以幫助使用這門程式語言的程式設計師在參與各種規模的專案時編寫出思路清晰的、合乎邏輯的程式碼。在使用 Python 編寫程式碼時,開發者們通常會遵循「優雅、明確、簡單」的核心準則,具體來說就是:
優美優於醜陋。明瞭優於隱晦。
簡單優於複雜。複雜優於凌亂。
扁平優於巢狀。稀疏優於稠密。
可讀性很重要。
上述準則確保了開發者們在使用 Python 語言時一般會拒絕花俏的語法,而選擇明確且儘可能沒有歧義的語法。當然了,對於這些準則的堅守也導致了 Python 社群對於犧牲了優雅特性的優化策略持有了較為謹慎的態度,一些對非重要部分進行效能優化的修補程式通常很難被獲准合併到 Python 的官方實現 CPython 專案中,這也限制 Python 在某些對執行速度有較高要求領域的使用。到目前為止,人們主要將 Python 應用於以下領域,並開發了相應的程式庫與框架:
基本上,除了基本語法之外,一個 Python 開發者的能力實際上就取決於如何根據自己面對的問題找到適用的框架,並在合理的時間內掌握該框架的使用方法,並用它快速地構建自己的專案。在後續筆記中,我們將會利用具體的專案實踐來介紹如何構建這種「在做中學,在學中做」的能力。
在瞭解以上基本概念之後,接下來就可以來具體規劃一下要學習如何使用Python語言進行框架開發的學習路線圖了。大致上,我們可以將路線圖劃分為以下三個里程碑。
要想學習接下來要介紹的內容,掌握 Python 語言的基本語法及其標準庫的使用方法無疑是先決條件。雖然在這個系列筆記中,我們會設定自己已經掌握了這門語言的基本使用,但對於「掌握」程度,我們還是希望先和讀者約定以下標準。首先,自然是要能正確地安裝 Python 語言執行環境,掌握這一能力的標準是讀者能在自己的計算機環境中順利地執行以下 Hello World 程式:
#! /usr/bin/env python
def main():
print("hello world!")
if __name__ == '__main__':
main()
接下來,讀者需要掌握的是 Python 語言的標準語法,包括靈活運用各種表示式語句、條件語句、迴圈語句,以及會使用標準庫提供的各種資料型別和資料結構,掌握這一能力的標準是能理解下面程式碼中實現的各種排序演演算法,並能正確地呼叫它們:
#! /usr/bin/env python
import random
def selectionSort(coll):
if(coll == []): return []
for i in range(len(coll)-1,0,-1):
max_j = i
for j in range(i):
if coll[j] > coll[max_j]: max_j = j
coll[i], coll[max_j] = coll[max_j], coll[i]
return coll
def countingSort(coll):
if(coll == []): return []
endl = len(coll)
minv = min(coll)
maxv = max(coll)
temp = [0 for i in range(maxv - minv + 1)]
for i in range(endl):
temp[coll[i] - minv] += 1
index = 0
for i in range(minv, maxv + 1):
for j in range(temp[i - minv]):
coll[index] = i
index += 1
return coll
def radixSort(coll, length):
if(coll == []): return []
for d in xrange(length):
LSD = [[] for _ in xrange(10)]
for n in coll:
LSD[n / (10 ** d) % 10].append(n)
coll = [tmp_a for tmp_b in LSD for tmp_a in tmp_b]
return coll
def bucketSort(coll):
if(coll == []): return []
length = len(coll)
buckets = [[] for _ in xrange(length)]
for tmp_a in coll:
buckets[int(length * tmp_a)].append(tmp_a)
tmp_coll = []
for tmp_b in buckets:
tmp_coll.extend(insertSort(tmp_b))
return tmp_coll
def insertSort(coll):
if(coll == []): return []
for i in range(1,len(coll)):
j = i
while j > 0 and coll[j-1] > coll[j]:
coll[j-1], coll[j] = coll[j], coll[j-1]
j -= 1
return coll
def shellSort(coll):
if(coll == []): return []
size = len(coll)
step = size / 2
while(step >= 1):
for i in range(step, size):
tmp = coll[i]
ins = i
while(ins >= step and tmp < coll[ins - step]):
coll[ins] = coll[ins - step]
ins -= step
coll[ins] = tmp
step = step / 2
return coll
def bubbleSort(coll):
if(coll == []): return []
endl = len(coll)
for i in range(endl, 0, -1):
for j in range(0, i - 1):
if(coll[j] > coll[j + 1]):
coll[j], coll[j + 1] = coll[j + 1], coll[j]
def quickSort(coll):
if(coll == []): return []
return quickSort([x for x in coll[1:] if x < coll[0]]) + \
coll[0:1] + \
quickSort([x for x in coll[1:] if x >= coll[0]])
最後,在最理想的情況下,讀者還應該具備一些針對某一特定任務來編寫自動化指令碼的能力,例如能理解並複述下面這段實現 Git 提交操作的自動化指令碼。
#! /usr/bin/env python
import os
import sys
import time
if not len(sys.argv) in range(2, 4):
print("Usage: git_commit.py <git_dir> [commit_message]")
exit(1)
title = "= Starting " + sys.argv[0] + "...... ="
n = len(title)
print(n*'=')
print(title)
print(n*'=')
os.chdir(sys.argv[1])
print("work_dir: " + sys.argv[1])
if len(sys.argv) == 3 and sys.argv[2] != "":
commit_message = sys.argv[2]
else:
commit_message = "committed at " + time.strftime("%Y-%m-%d",time.localtime(time.time()))
os.system("git add .")
os.system("git commit -m '"+ commit_message + "'")
print("Commit is complete!")
print(n*'=')
print("= Done!" + (n-len("= Done!")-1)*' ' + "=")
print(n*'=')
如果讀者在基於以上標準的自我檢驗中遇到了一些不可迴避的問題,我們會強烈建議先回過頭去補習一下 Python 語言的基礎知識,例如去閱讀一下《Python 基礎教學》或者其他介紹了上述基礎的書籍,等達到了我們在這裡約定的對基礎知識的「掌握」標準,再繼續學習後面的內容,以便實現最好的學習效果。
這一里程碑主要聚焦的是可持續之學習能力。眾所周知,在如今的軟體開發活動中,我們可以選擇的開發框架不僅琳琅滿目,選擇眾多,而且新陳代謝極為快速。這意味著,即使某一本書介紹了當前最為流行的框架及其具體使用方法,很有可能等到它最終出版之時,開發者們已經有了更好的選擇。所以授之以魚不如授之以漁,真正的目的是要掌握「快速學習新框架」的能力,這需要我們掌握如何閱讀這些框架本身提供的官方檔案,以便自行去了解這些框架的設計思路,並理解為什麼決定開放那些介面給使用者,為什麼對使用者隱藏那些實現。這就需要讀者自己具備開發框架的能力。換句話說,雖然不必重複發明輪子,但一個優秀的工程師或設計師應該瞭解輪子是如何被髮明的,這樣才能清楚在怎麼樣的輪子上構建怎麼樣的車。
總而言之,對於如今的項軟體工程師來說,在一個月內快速掌握某個新框架的能力遠比之前已經掌握了多少個框架重要得多,例如當開發團隊的管理員在面試新成員時,如果這位面試者有五年 A 框架的使用經驗,那固然是很好,但團隊中很多人都有,未必需要再多一個同型別的人才、但如果該面試者能在一個禮拜快速上手基於 Python 的任意一種框架,那麼這位人才的重要性就會被凸顯出來。畢竟如果我是一個開發團隊的管理者,肯定不會喜歡團隊的成員告訴我這個不會,那個不會。