怎样才算精通Python?
在這篇文章中,我會1)先給出我對精通Python的理解;2)然后給出一些Python中有難度的知識點。如果大家在看完這篇文章之前,已經充分理解了我列出的各個知識點,那么,我相信你已經算是精通Python了。如果不能,我希望這篇回答能讓你意識到自己Python知識還存在哪些不足,在之后的學習中,從哪些方面去改進。
一
精通是個偽命題
怎樣才算精通Python,這是一個非常有趣的問題。
很少有人會說自己精通Python,因為,這年頭敢說精通的人都會被人摁在地上摩擦。其次,我們真的不應該糾結于編程語言,而應該專注于領域知識。比如,你可以說你精通數據庫,精通分布式,精通機器學習,那都算你厲害。但是,你說你精通Python,這一點都不酷,在業界的認可度也不高。
再者,Python使用范圍如此廣泛,可以說是世界上使用領域最廣的編程語言(沒有之一)。一個人精力有限,不可能精通所有的領域。就拿Python官網的Python應用領域來說,Python有以下幾個方面的應用:
Web Programming: Django, Pyramid, Bottle, Tornado, Flask, web2py
GUI Development: wxPython, tkInter, PyGtk, PyGObject, PyQt
Scientific and Numeric: SciPy, Pandas, IPython
Software Development: Buildbot, Trac, Roundup
System Administration: Ansible, Salt, OpenStack
如果有人真的精通上面所有領域,那么,請收下我的膝蓋,并且,請收我為徒。
既然精通Python是不可能也是沒有意義的事情,那么,為什么各個招聘要求里面,都要求精通Python呢?我覺得這都是被逼的。為什么這么說呢,且聽我慢慢說來。
1
為什么招聘要求精通Python
絕大部分人對Python的認識都有偏差,認為Python比較簡單。相對于C、C++和Java來說,Python確實比較容易學習一些。所以,才會有這么多只是簡單地了解了一點語法,就聲稱自己會Python的工程師。
打個比方,如果一個工程師,要去面試一個C++的崗位,他至少會找一本C++的書認真學習,然后再去應聘。Python則不然,很多同學只花了一點點時間,了解了一下Python的語法,就說自己熟悉Python。這也導致Python的面試官相對于其他方向的面試官,更加容易遇到不合格的求職者,浪費了大家的時間。Python面試官為了不給自己找麻煩,只能提高要求,要求求職者精通Python。
2
怎樣才算精通Python
既然精通Python本身是一件不可能的事情,而面試官又要求精通Python,作為求職者,應該達到怎樣的水平,才敢去應聘呢?我的觀點是,要求精通Python的崗位都是全職的Python開發,Python是他們的主要使用語言,要想和他們成為同事,你至少需要:
1. 能夠寫出Pythonic的代碼
2. 對Python的一些高級特性比較熟悉
3. 對Python的優缺點比較了解
二
敢來挑戰嗎?
前面的幾點要求說出來可能比較抽象,不太好理解。我們來看幾個例子,如果能夠充分理解這里的每一個例子,那么,你完全能夠順利通過"精通Python"的崗位面試。
1
上下文管理器
大家在編程的時候,經常會遇到這樣的場景:先執行一些準備操作,然后執行自己的業務邏輯,等業務邏輯完成以后,再執行一些清理操作。
比如,打開文件,處理文件內容,最后關閉文件。又如,當多線程程序需要訪問臨界資源的時候,線程首先需要獲取互斥鎖,當執行完成并準備退出臨界區的時候,需要釋放互斥鎖。對于這些情況,Python中提供了上下文管理器(Context Manager)的概念,可以通過上下文管理器來控制代碼塊執行前的準備動作以及執行后的收尾動作。
我們以處理文件為例來看一下在其他語言中,是如何處理這種情況的。 Java風格/C++風格的Python代碼:
Pythonic的代碼:
我們這個問題討論的是精通Python,顯然,僅僅是知道上下文管理器是不夠的,你還需要知道:
1.1 上下文管理器的其他使用場景(如數據庫cursor,鎖)
上下文管理器管理鎖
上下文管理器管理數據庫cursor
上下文管理器控制運算精度
1.2 上下文管理器可以同時管理多個資源
假設你需要讀取一個文件的內容,經過處理以后,寫入到另外一個文件中。你能寫出Pythonic的代碼,所以你使用了上下文管理器,滿意地寫出了下面這樣的代碼:
你已經做得很好了,但是,你時刻要記住,你是精通Python的人啊!精通Python的人應該知道,上面這段代碼還可以這么寫:
1.3 在自己的代碼中,實現上下文管理協議
你知道上下文管理器的語法簡潔優美,寫出來的代碼不但短小,而且可讀性強。所以,作為精通Python的人,你應該能夠輕易地實現上下文管理協議。在Python中,我們就是要自己實現下面兩個協議:
__enter__(self)?
__exit__(self, exception_type, exception_value, traceback)?
當然,更優美的方法是使用contextmanager裝飾器。
2
裝飾器
由于我們這里討論的是精通Python,所以,我假設大家已經知道裝飾器是什么,并且能夠寫簡單的裝飾器。那么,你是否知道,寫裝飾器也有一些注意事項呢。
我們來看一個例子:
我們用裝飾器裝飾完函數以后,無法正確地獲取到原函數的函數名稱和幫助信息,為了獲取這些信息,我們需要使用@functool.wraps。 如下所示:
再比如,我們要獲取被裝飾的函數的參數,以進行判斷,如下所示:
這段代碼看起來沒有任何問題,但是,執行將會出錯,因為,username是一個位置參數,而不是一個關鍵字參數。我們在裝飾器里面,通過kwargs.get('username')是獲取不到username這個變量的。為了保證靈活性,我們可以通過inspect來修改裝飾器的代碼,如下所示:
裝飾器還有很多知識,比如裝飾器的使用場景,裝飾器有哪些缺點,這些你們都知道嗎?
3
全局變量
關于Python的全局變量,我們先從一個問題開始:Python有沒有全局變量?可能你看到這個問題的時候就蒙圈了,沒關系,我來解釋一下。
從Python自己的角度來說,Python是有全局變量的,所以,Python為我們提供了global關鍵字,我們能夠在函數里面修改全局變量。但是,從C/C++程序員的角度來說,Python是沒有全局變量的。因為,Python的全局變量并不是程序級別的(即全局唯一),而是模塊級別的。模塊就是一個Python文件,是一個獨立的、頂層的命名空間。模塊內定義的變量,都屬于該命名空間下,Python并沒有真正的全局變量,變量必然屬于某一個模塊。
我們來看一個例子,就能夠充分理解上面的概念。三種不同的修改全局變量的方法:
這段代碼雖然看起來都是在對全局變量操作,其實,還涉及到命名空間和模塊的工作原理,如果不能很清楚的知道發生了什么,可能需要補充一下自己的知識了。
4
時間復雜度
我們都知道,在Python里面list是異構元素的集合,并且能夠動態增長或收縮,可以通過索引和切片訪問。那么,又有多少人知道,list是一個數組而不是一個鏈表。
關于數組和鏈表的知識,這里就不再贅述。如果我們在寫代碼的過程中,對于自己最常用的數據結構,連它的時間復雜度都不知道,我們又怎么能夠寫出高效的代碼呢。寫不出高效的代碼,那我們又怎么能夠聲稱自己精通這門編程語言呢。
既然list是一個數組,那么,我們要使用鏈表的時候,應該使用什么數據結構呢?在寫Python代碼的時候,如果你需要一個鏈表,你應該使用標準庫collections中的deque, deque是雙向鏈表。標準庫里面有一個queue,看起來和deque有點像,它們是什么關系?這個問題留著讀者自己回答。
我們再來看一個很實際的例子:有兩個目錄,每個目錄都有大量文件,求兩個目錄中都有的文件,此時,用Set比List快很多。因為,Set的底層實現是一個hash表,判斷一個元素是否存在于某個集合中,List的時間復雜度為O(n),Set的時間復雜度為O(1),所以這里應該使用Set。我們應該非常清楚Python中各個常用數據結構的時間復雜度,并在實際寫代碼的過程中,充分利用不同數據結構的優勢。
5
Python中的else
最后我們來看一個對Python語言優缺點理解的例子,即Python中增加的兩個else。相對于C++語言或者Java語言,Python語法中多了兩個else。
一個在while循環或for循環中:
另一個在try...except語句中:
那么,哪一個是好的設計,哪一個是不好的設計呢?要回答這個問題,我們先來看一下在大家固有的觀念中,else語句起到什么作用。在所有語言中,else都是和if語句一起出現的:
翻譯成自然語言就是,如果條件滿足,則執行語句1,否則,執行語句2。注意我們前面的用語,是否則,也就是說,else語句在我們固有的觀念中,起到的作用是“否則”,是不滿足條件的情況下才執行的。
我們來看Python中,while循環后面的else語句。這個else語句是在while語句正常結束的時候執行的。所以,按照語意來說,while循環的else起到的作用是and。也就是說,在Python中,while循環末尾的else換做and才是更加合適的。
你可能覺得我有點鉆牛角尖,那好,我再強調一遍,while循環中的else語句是在循環正常結束的時候執行的,那么請問:
1. 如果while循環里面遇到了break語句,else語句會執行嗎
2. 如果while循環最后,遇到了continue語句,else語句還會執行嗎
3. 如果while循環內部出現異常,else語句還會執行嗎
這里的幾個問題,大多數人都不能夠很快的正確回答出來。而我們的代碼是寫給人看的,不應該將大多數人排除在能夠讀懂這段代碼之外。所以我認為,Python語言中循環語句末尾的else語句是一個糟糕的設計。
現在,我們再來看try...except語句中的else,這個else設計得特別好,其他語言也應該吸取這個設計。這個設計的語義是,執行try里面的語句,這里面的語句可能會出現異常,如果出現了異常,就執行except里面的語句,如果沒有出現異常,就執行else里面的語句,最后,無論是否出現異常,都要執行finally語句。這個設計好就好在,else的語句完全和我們的直觀感受是一樣的,是在沒有出現異常的情況下執行。并且,有else比沒有else好,有了else以后,正確地將程序員認為可能出現異常的代碼和不可能出現異常的代碼分開,這樣,更加清楚的表明了是哪一條語句可能會出現異常,更多的暴露了程序員的意圖,使得代碼維護和修改更加容易。
三
結論
我這里想說的是,Python是一門編程語言,使用范圍非常廣泛,大家不要去追求精通Python程序語言自身,而應該將精力放在自己需要解決的實際問題上。其次,絕大多數人對Python的認識都存在誤區,認為Python很簡單,只是簡單地了解一下就開始寫Python代碼,寫出了一堆很不好維護的代碼,我希望這一部分人看到我的回答以后,能夠回去重新學習Python。最后,對于一些同學的疑慮——招聘職位要求精通Python,我的回答是,他們并不奢望招到一個精通Python的人,他們只是想招到一個合格的工程師,而大部分的Python工程師都不合格!
END
推薦閱讀
MongoDB的正確使用姿勢
Kylin性能調優記——業務技術兩手抓
大數據平臺的服務內容以及猛犸大數據平臺近期的思考
MySQL 5.7新特性介紹
NOS的利器—富媒體處
點擊“閱讀原文”,查看更多技術干貨
總結
以上是生活随笔為你收集整理的怎样才算精通Python?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网易云信新增用户、IM、实时音视频多维度
- 下一篇: 【新年快乐】网易云信春节期间服务公告