先不講數據結構了,此次來講說python中一些不被注意的功能。java
在python的設計哲學中,有這麼一條內容:「Simple is better than complex」,簡單的代碼比複雜的要好,這也是爲何python被推薦爲初學者必學的語言。不少人初學python,每每會受到其餘語言的影響,好比以前學過java的,把python代碼寫的像java同樣。舉個例子,在java中設計一個類時,咱們經常會爲內部變量定義get和set方法,這是保證封裝性的重要手段,可是在python中卻不建議這樣作,python中的內部變量使用單下劃線表示(好比self.__name
),不過這樣定義了仍是能夠訪問到私有變量。怎麼說?python中使用約定,我不會強制說這個變量你不能訪問,可是你最好不要這樣作。若是須要對變量進行其餘操做,使用@parameter裝飾器進行get和set封裝,這樣直接訪問內部變量會出錯。講偏了,關於類和對象這方面的內容之後再說。python
你若是打開python交互環境,輸入import this
能夠看到如下內容:正則表達式
The 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. 複雜賽過凌亂this
Flat is better than nested. 扁平勝於嵌套spa
Sparse is better than dense. 間隔勝於緊湊設計
......
這些是python的設計哲學,後面還有一些沒列出來,在寫python代碼時最好聽從這些設計哲學。
第一個功能。
若是讓你寫一段代碼表示a大於2且小於10,大多數人都會用a > 2 && a < 10
對吧,在python中你能夠直接使用2 < a < 10
。
a = 5 # 能夠這樣 print(2 < a < 10) # 也能夠這樣 print(10 > a <= 9)
True True
還有一個不少人可能都知道的技巧,就地交換值,而不須要中間變量。
a = 2 b = 3 print(a, b) # 直接交換 a, b = b, a print(a, b)
2 3 3 2
第二個功能。
咱們經常會須要用for循環來遍歷序列中的值,而後進行某些操做。在其餘語言中你可能這麼寫:
a = ['a', 'b', 'c', 'd', 'e'] for(int i = 0; i < len(a); i++): print(a[i])
在python中不少人會這麼寫,對a的長度使用range生成一個序列,而後遍歷。
a = ['a', 'b', 'c', 'd', 'e'] # 對a的長度使用range生成一個序列,而後遍歷 for i in range(len(a)): print(a[i])
a b c d e
其實你能夠這樣寫,直接使用enumerate方法,它會返回序列的下標和值。
a = ['a', 'b', 'c', 'd', 'e'] # 對a的長度使用range生成一個序列,而後遍歷 for i in enumerate(a): print(i) # 或者這樣 for index, value in enumerate(a): print(index, value)
(0, 'a') (1, 'b') (2, 'c') (3, 'd') (4, 'e') 0 a 1 b 2 c 3 d 4 e
第三個功能。
通常狀況下,循環語句和條件判斷語句是互不相干的,if後面就是else,for以後是in。其實循環語句後面也能夠跟着else。for以後跟着else的意思是,運行這個循環,而後執行else中的語句。
for i in foo: if i == 0: break else: print("i was never 0")
除了for循環後面能夠跟着else,while和try/except以後也能夠跟着else。
第四個功能。
用過字典的都知道,若是咱們須要字典中某個鍵的值,可使用d['key']
來獲取,若是key不存在的話會拋出異常,這樣確定很差了,若是使用d.get('key')
,在key值不存在時會默認返回None,這樣就不用關心是否會有異常發生。其實還能夠這樣,d.get('key', 0)
,第二個參數指定key不存在時用來代替的值。
第五個功能。
正則表達式是個很讓人頭疼的東西,若是能加上註釋該多好,這樣我就知道本身寫的是什麼了。在Python中你能夠這樣。
# 對每個規則使用引號括起來 pattern = ( "^" # beginning of string "M{0,4}" # thousands - 0 to 4 M's "(CM|CD|D?C{0,3})" # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's), # or 500-800 (D, followed by 0 to 3 C's) "(XC|XL|L?X{0,3})" # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's), # or 50-80 (L, followed by 0 to 3 X's) "(IX|IV|V?I{0,3})" # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's), # or 5-8 (V, followed by 0 to 3 I's) "$" # end of string ) print(pattern) # 而後bapattern放入對應的re匹配方法中。
^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$
第六個功能。
在上一篇迭代器和生成器中說過,iter()函數能夠生成一個迭代器,以後你就能使用循環或者next方法來產出值。其實iter還接受第二個參數,它的做用是在迭代的過程當中若是碰到第二個參數則中止。看個例子:
def seek_next_line(f): for c in iter(lambda: f.read(1),'\n'): pass
上面的代碼中,從f中循環讀入,若是碰到\n
則結束讀取。
其餘的技巧像使用生成器表達式,利用拆包方法等等,以前都有說過,這裏再也不贅述。
本人才疏學淺,上文中不免有些錯誤,還請各位品評指正。若是以爲寫的還行,歡迎關注個人公衆號MLGroup,帶你走進機器學習的世界。