天天看點

高效提升python程式設計的幾種方式—搞他 

前言

我們知道Python這門語言在運作速度上已經敗給了許多别的語言(比如C, C++, Java, Golang....).但從一個開發者的角度來看Python是我最喜歡的語言,很大一部分原因在于其文法簡單(其實是我比較懶),還有很多很sao的操作,可以大大提高我們的敲代碼的效率.我們通常叫這種sao操作為pythonic.

Python的sao操作很多,這裡先介紹幾種,以後慢慢更.

1.交換兩個變量

傳統寫法:

temp = a
a = b
b = temp
      

pythonic:

a, b = b, a
      

2.枚舉enumerate

設想一個場景,有一個清單["老胡", "老王", "老李", "老趙"],現在要求你建立一個字典,其中字典的每一項key為清單的元素,value為對應元素的下标,該怎麼做?這并不是枚舉的最佳使用場景,這裡隻是一個例子,告訴你們枚舉其實很好用.

傳統寫法:

alist = ["老胡", "老王", "老李", "老趙"]
aDict = {}
for i in range(len(alist)):
 aDict[alist[i]] = i
      

pythonic:

alist = ["老胡", "老王", "老李", "老趙"]
aDict = {}
for index, item in enumerate(alist):
 aDict[item] = index
      

3.推導式

Python中的推導式分為三種清單推導式,字典推導式,集合推導式,由于集合推導式和清單推導式神似這裡就不在過多示範.

清單推導式

設想一個場景,要求你把1-100間的所有偶數放到清單evenList中

傳統寫法:

evenList = []
for i in range(0, 101):
 if i % 2 == 0:
 evenList.append(i)
      

pythonic:

evenList = [i for i in range(0,101) if i % 2 == 0]
      

隻用一行代碼是不是很爽呢.

給出清單推導式的規範:

variable = [out_exp for out_exp in input_list if 某個條件成立]
      

字典推導式

設想一個場景,這裡要求你把一個字典裡所有的key和value位置交換

傳統寫法:

ADict = {
 "key1": "value1",
 "key2": "value2",
 "key3": "value3"
}
BDict = {}
for key, value in ADict.items():
 BDict[value] = key
      

pythonic:

ADict = {
 "key1": "value1",
 "key2": "value2",
 "key3": "value3"
}
BDict = {value: key for key, value in ADict.items()}
      

熟練使用推導式可以讓你的代碼變得十分的簡短!

4.lambda表達式

這無疑是一個非常重要的文法,然而很多新手卻不喜歡使用...

所謂lambda表達式就是匿名函數,我們為什麼要使用匿名函數呢?有些時候我們想要使用一個函數但是整個程式中隻需要使用這一次,這時候使用lambda表達式無疑最友善了

設想一個場景,有一個清單裡面存放着一對對的元組,現在要按元組的第二個元素對該清單進行排序

傳統方法:

aList = [(2, 3), (1, 2), (4, 5), (7, 4)]
def sortKey(x):
 return x[1]
aList.sort(key=sortKey) # 注意不要寫成aList = aList.sort(key=sortKey),它沒有傳回值
print(aList)
      

out:

[(1, 2), (2, 3), (7, 4), (4, 5)]
      

pythonic:

aList = [(2, 3), (1, 2), (4, 5), (7, 4)]
aList.sort(key=lambda x: x[1])
      

out:

[(1, 2), (2, 3), (7, 4), (4, 5)]
      

給出規範:

lambda 參數:操作(參數)
      

注意後面的操作(參數)是要傳回的

舉個例子:

add = lambda x, y: x + y
# 等價于下面的函數
def add(x, y):
 return x + y
      

5.裝飾器

裝飾器是Python非常非常非常重要的知識點,這裡隻做應用舉例,以後我會出一期詳細的講解裝飾器

設想一個場景,公司有好多的部門(函數)在同時運作,現在要求你在不改變運作代碼的條件下,給每個部門新加一個功能

源代碼:

def partA():
 print("----do A job----")
def partB():
 print("----do B job----")
def partC():
 print("----do C job----")
if __name__ == '__main__':
 partA()
 partB()
 partC()
      

out:

----do A job----
----do B job----
----do C job----
      

傳統方法:

def partA():
 print("----do A job----")
 print("****do extra job****")
def partB():
 print("----do B job----")
 print("****do extra job****")
def partC():
 print("----do C job----")
 print("****do extra job****")
if __name__ == '__main__':
 partA()
 partB()
 partC()
      

out:

----do A job----
****do extra job****
----do B job----
****do extra job****
----do C job----
****do extra job****
      

pythonic:

def doExtraJob(func):
 def wrap():
 func()
 print("****do extra job****")
 return wrap
@doExtraJob
def partA():
 print("----do A job----")
@doExtraJob
def partB():
 print("----do B job----")
@doExtraJob
def partC():
 print("----do C job----")
if __name__ == '__main__':
 partA()
 partB()
 partC()
      

out:

----do A job----
****do extra job****
----do B job----
****do extra job****
----do C job----
****do extra job****
      

對比兩種方法,使用裝飾器的效果就是可以讓一個函數再不改變内部代碼的情況下增加新的功能.

6.神奇的else語句

大部分人隻知道else語句和if語句一起使用,但是你們知道嗎else語句也可以和for語句,while語句,try語句一起使用

設想一個場景,你在對一個内部資料未知的清單進行循環時(不論是for還是while),你設定了一個遇到偶數就break的語句,倘若數組裡不含偶數就輸出奇數清單字樣.

傳統方法:

aList = [1, 3, 5, 7, 9]
flag = True
for i in aList:
 if i % 2 == 0:
 flag = False
 break
if flag:
 print("奇數清單")
      

pythonic:

aList = [1, 3, 5, 7, 9]
for i in aList:
 if i % 2 == 0:
 flag = False
 break
else:
 print("奇數清單")
      

注意,循環中(for或while)的else語句會在循環正常退出時(即不是由于break語句退出時)觸發

對與try,else語句,else語句會在沒有異常時被觸發,也許你們會有疑問,沒有異常直接在try語句裡不是解決了嗎,但是try語句裡的操作會被捕獲,有些時候我們并不想這樣.

看個例子:

try:
 assert True
except:
 print("出錯了")
else:
 print("沒有錯")
      

out:

沒有錯
      

assert為斷言當其後面的語句為假是會報出異常,這和try語句一起使用有時候會非常的友善.

7.map函數

map函數會将一個函數映射到一個清單的所有元素上去.這和lambda表達式配合簡直完美.

設想一個場景,一個清單裡有1-10十個數,現要求你将這個清單裡的每一個數的平方存入另一個清單,這并不難

傳統方法:

aList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
bList = []
for i in aList:
 bList.append(i**2)
      

pythonic:

aList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
bList = list(map(lambda x:x**2, aList))
      

千萬注意map函數傳回的不是清單是個map對象,需要類型轉換

8.filter函數

沒錯從函數的名字就可以看出filter函數的功能是過濾,filter可以過濾一個清單的元素并傳回所有符合要求的元素組成的filter對象,和map類似注意類型轉換.

設想一個場景,有一個清單,裡面存放着一些未知的數字,現在要求你把所有的偶數挑選出來,

傳統方法:

aList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
bList = []
for each in aList:
 if each % 2 == 0:
 bList.append(each)
      

pythonic:

aList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
bList = list(filter(lambda x: not x % 2, aList))
      

這裡使用not是因為偶數除2的餘數為0(Python中0為False),為了讓偶數時傳回True,用來一個not

9.reduce函數

注意:和前兩個函數不同,reduce函數被放到了functools這個子產品裡,使用時需要導入.

reduce函數會将一個清單裡的所有元素都用一個函數進行運算,要求這個函數必須有兩個參數.

設想一個場景,要求求一個數字清單裡所有的數字的平均值.

傳統方法:

aList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sum = 0
for i in aList:
 sum += i
ave = sum / len(aList)
      

pythonic:

from functools import reduce
aList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ave = reduce(lambda x, y: x + y, aList) / len(aList)
      

map,filter,reduce函數和lambda配合使用才是精華所在.還有千萬别弄混三個函數的功能

函數名功能傳回值map單純的将一個函數映射到一個清單的所有元素上去map對象filter過濾一個清單的元素并傳回所有符合要求的元素組成的filter對象filter對象reduce将一個清單裡的所有元素都用一個函數進行運算計算結果

10.總結

Python的sao操作還有很多,這次希望這次帶來的幾個用法對你們有所幫助,對于剛接觸的人來說很容易忘記,希望大家可以多動手敲敲代碼加強記憶,看看你們之前寫的代碼可不可以用這些sao操作改一改,使你的代碼看上去更加精簡.