python写算法太慢_程序运行慢?你怕是写的假 Python
Python程序運行太慢的一個可能的原因是沒有盡可能的調(diào)用內(nèi)置方法,下面通過5個例子來演示如何用內(nèi)置方法提升Python程序的性能。
1. 數(shù)組求平方和
輸入一個列表,要求計算出該列表中數(shù)字的的平方和。最終性能提升了1.4倍。
首先創(chuàng)建一個長度為10000的列表。
arr?=?list(range(10000))
1.1 最常規(guī)的寫法
while循環(huán)遍歷列表求平方和。平均運行時間2.97毫秒。
def?sum_sqr_0(arr):
res?=?0
n?=?len(arr)
i?=?0
while?i?
res?+=?arr[i]?**?2
i?+=?1
return?res
%timeit?sum_sqr_0(arr)
2.97?ms?±?36.4?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?100?loops?each)
1.2 for range代替while循環(huán)
避免i += 1的變量類型檢查帶來的額外開銷。平均運行時間2.9毫秒。
def?sum_sqr_1(arr):
res?=?0
for?i?in?range(len(arr)):
res?+=?arr[i]?**?2
return?res
%timeit?sum_sqr_1(arr)
2.9?ms?±?137?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?100?loops?each)
1.3for x in arr代替for range
避免arr[i]的變量類型檢查帶來的額外開銷。平均運行時間2.59毫秒。
def?sum_sqr_2(arr):
res?=?0
for?x?in?arr:
res?+=?x?**?2
return?res
%timeit?sum_sqr_2(arr)
2.59?ms?±?89?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?100?loops?each)
1.4 sum函數(shù)套用map函數(shù)
平均運行時間2.36毫秒
def?sum_sqr_3(arr):
return?sum(map(lambda?x:?x**2,?arr))
%timeit?sum_sqr_3(arr)
2.36?ms?±?15.1?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?100?loops?each)
1.5 sum函數(shù)套用生成器表達式
生成器表達式如果作為某個函數(shù)的參數(shù),則可以省略掉()。平均運行時間2.35毫秒。
def?sum_sqr_4(arr):
return?sum(x?**?2?for?x?in?arr)
%timeit?sum_sqr_4(arr)
2.35?ms?±?107?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?100?loops?each)
1. 6 sum函數(shù)套用列表推導(dǎo)式
平均運行時間2.06毫秒。
def?sum_sqr_5(arr):
return?sum([x?**?2?for?x?in?arr])
%timeit?sum_sqr_5(arr)
2.06?ms?±?27.2?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?100?loops?each)
2. 字符串拼接
輸入一個列表,要求將列表中的字符串的前3個字符都拼接為一個字符串。最終性能提升了2.1倍。
首先創(chuàng)建一個列表,生成10000個隨機長度和內(nèi)容的字符串。
from?random?import?randint
def?random_letter():
return?chr(ord('a')?+?randint(0,?25))
def?random_letters(n):
return?"".join([random_letter()?for?_?in?range(n)])
strings?=?[random_letters(randint(1,?10))?for?_?in?range(10000)]
2.1 最常規(guī)的寫法
while循環(huán)遍歷列表,對字符串進行拼接。平均運行時間1.86毫秒。
def?concat_strings_0(strings):
res?=?""
n?=?len(strings)
i?=?0
while?i?
res?+=?strings[i][:3]
i?+=?1
return?res
%timeit?concat_strings_0(strings)
1.86?ms?±?74.9?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
2.2for range代替while循環(huán)
避免i += 1的變量類型檢查帶來的額外開銷。平均運行時間1.55毫秒。
def?concat_strings_1(strings):
res?=?""
for?i?in?range(len(strings)):
res?+=?strings[i][:3]
return?res
%timeit?concat_strings_1(strings)
1.55?ms?±?32.9?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
2.3for x in strings代替for range
避免strings[i]的變量類型檢查帶來的額外開銷。平均運行時間1.32毫秒。
def?concat_strings_2(strings):
res?=?""
for?x?in?strings:
res?+=?x[:3]
return?res
%timeit?concat_strings_2(strings)
1.32?ms?±?19.5?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
2.4 .join方法套用生成器表達式
平均運行時間1.06毫秒。
def?concat_strings_3(strings):
return?"".join(x[:3]?for?x?in?strings)
%timeit?concat_strings_3(strings)
1.06?ms?±?15.2?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
2.5 .join方法套用列表解析式
平均運行時間0.85毫秒。
def?concat_strings_4(strings):
return?"".join([x[:3]?for?x?in?strings])
%timeit?concat_strings_4(strings)
858?μs?±?14.5?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
3. 篩選奇數(shù)
輸入一個列表,要求篩選出該列表中的所有奇數(shù)。最終性能提升了3.6倍。
首先創(chuàng)建一個長度為10000的列表。
arr?=?list(range(10000))
3.1 最常規(guī)的寫法
創(chuàng)建一個空列表res,while循環(huán)遍歷列表,將奇數(shù)append到res中。平均運行時間1.03毫秒。
def?filter_odd_0(arr):
res?=?[]
i?=?0
n?=?len(arr)
while?i?
if?arr[i]?%?2:
res.append(arr[i])
i?+=?1
return?res
%timeit?filter_odd_0(arr)
1.03?ms?±?34.1?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
3.2for range代替while循環(huán)
避免i += 1的變量類型檢查帶來的額外開銷。平均運行時間0.965毫秒。
def?filter_odd_1(arr):
res?=?[]
for?i?in?range(len(arr)):
if?arr[i]?%?2:
res.append(arr[i])
i?+=?1
return?res
%timeit?filter_odd_1(arr)
965?μs?±?4.02?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
3.3for x in arr代替for range
避免arr[i]的變量類型檢查帶來的額外開銷。平均運行時間0.430毫秒。
def?filter_odd_2(arr):
res?=?[]
for?x?in?arr:
if?x?%?2:
res.append(x)
return?res
%timeit?filter_odd_2(arr)
430?μs?±?9.25?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
3.4 list套用filter函數(shù)
平均運行時間0.763毫秒。注意filter函數(shù)很慢,在Python 3.6里非常雞肋。
def?filter_odd_3(arr):
return?list(filter(lambda?x:?x?%?2,?arr))
%timeit?filter_odd_3(arr)
763?μs?±?15.9?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
3.5 list套用生成器表達式
平均運行時間0.398毫秒。
def?filter_odd_4(arr):
return?list((x?for?x?in?arr?if?x?%?2))
%timeit?filter_odd_4(arr)
398?μs?±?16.4?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
3.6 帶條件的列表推導(dǎo)式
平均運行時間0.290毫秒。
def?filter_odd_5(arr):
return?[x?for?x?in?arr?if?x?%?2]
%timeit?filter_odd_5(arr)
290?μs?±?5.54?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
4. 兩個數(shù)組相加
輸入兩個長度相同的列表,要求計算出兩個列表對應(yīng)位置的數(shù)字之和,返回一個與輸入長度相同的列表。最終性能提升了2.7倍。
首先生成兩個長度為10000的列表。
arr1?=?list(range(10000))
arr2?=?list(range(10000))
4.1 最常規(guī)的寫法
創(chuàng)建一個空列表res,while循環(huán)遍歷列表,將兩個列表對應(yīng)的元素之和append到res中。平均運行時間1.23毫秒。
def?arr_sum_0(arr1,?arr2):
i?=?0
n?=?len(arr1)
res?=?[]
while?i?
res.append(arr1[i]?+?arr2[i])
i?+=?1
return?res
%timeit?arr_sum_0(arr1,?arr2)
1.23?ms?±?3.77?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
4.2for range代替while循環(huán)
避免i += 1的變量類型檢查帶來的額外開銷。平均運行時間0.997毫秒。
def?arr_sum_1(arr1,?arr2):
res?=?[]
for?i?in?range(len(arr1)):
res.append(arr1[i]?+?arr2[i])
return?res
%timeit?arr_sum_1(arr1,?arr2)
997?μs?±?7.42?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
4.3for i, x in enumerate代替for range
部分避免arr[i]的變量類型檢查帶來的額外開銷。平均運行時間0.799毫秒。
def?arr_sum_2(arr1,?arr2):
res?=?arr1.copy()
for?i,?x?in?enumerate(arr2):
res[i]?+=?x
return?res
%timeit?arr_sum_2(arr1,?arr2)
799?μs?±?16.7?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
4.4for x, y in zip代替for range
避免arr[i]的變量類型檢查帶來的額外開銷。平均運行時間0.769毫秒。
def?arr_sum_3(arr1,?arr2):
res?=?[]
for?x,?y?in?zip(arr1,?arr2):
res.append(x?+?y)
return?res
%timeit?arr_sum_3(arr1,?arr2)
769?μs?±?12.2?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
4.5 列表推導(dǎo)式套用zip
平均運行時間0.462毫秒。
def?arr_sum_4(arr1,?arr2):
return?[x?+?y?for?x,?y?in?zip(arr1,?arr2)]
%timeit?arr_sum_4(arr1,?arr2)
462?μs?±?3.43?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
5. 兩個列表相同元素的數(shù)量
輸入兩個列表,要求統(tǒng)計兩個列表相同元素的數(shù)量。其中每個列表內(nèi)的元素都是不重復(fù)的。最終性能提升了5000倍。
首先創(chuàng)建兩個列表,并將元素的順序打亂。
from?random?import?shuffle
arr1?=?list(range(2000))
shuffle(arr1)
arr2?=?list(range(1000,?3000))
shuffle(arr2)
5.1 最常規(guī)的寫法
while循環(huán)嵌套,判斷元素arr1[i]是否等于arr2[j],平均運行時間338毫秒。
def?n_common_0(arr1,?arr2):
res?=?0
i?=?0
m?=?len(arr1)
n?=?len(arr2)
while?i?
j?=?0
while?j?
if?arr1[i]?==?arr2[j]:
res?+=?1
j?+=?1
i?+=?1
return?res
%timeit?n_common_0(arr1,?arr2)
338?ms?±?7.81?ms?per?loop?(mean?±?std.?dev.?of?7?runs,?1?loop?each)
5.2for range代替while循環(huán)
避免i += 1的變量類型檢查帶來的額外開銷。平均運行時間233毫秒。
def?n_common_1(arr1,?arr2):
res?=?0
for?i?in?range(len(arr1)):
for?j?in?range(len(arr2)):
if?arr1[i]?==?arr2[j]:
res?+=?1
return?res
%timeit?n_common_1(arr1,?arr2)
233?ms?±?10.9?ms?per?loop?(mean?±?std.?dev.?of?7?runs,?1?loop?each)
5.3for x in arr代替for range
避免arr[i]的變量類型檢查帶來的額外開銷。平均運行時間84.8毫秒。
def?n_common_2(arr1,?arr2):
res?=?0
for?x?in?arr1:
for?y?in?arr2:
if?x?==?y:
res?+=?1
return?res
%timeit?n_common_2(arr1,?arr2)
84.8?ms?±?1.38?ms?per?loop?(mean?±?std.?dev.?of?7?runs,?10?loops?each)
5.4 使用if x in arr2代替內(nèi)層循環(huán)
平均運行時間24.9毫秒。
def?n_common_3(arr1,?arr2):
res?=?0
for?x?in?arr1:
if?x?in?arr2:
res?+=?1
return?res
%timeit?n_common_3(arr1,?arr2)
24.9?ms?±?1.39?ms?per?loop?(mean?±?std.?dev.?of?7?runs,?10?loops?each)
5.4 使用更快的算法
將數(shù)組用.sort方法排序,再進行單層循環(huán)遍歷。把時間復(fù)雜度從O(n2)降低到O(nlogn),平均運行時間0.239毫秒。
def?n_common_4(arr1,?arr2):
arr1.sort()
arr2.sort()
res?=?i?=?j?=?0
m,?n?=?len(arr1),?len(arr2)
while?i?
if?arr1[i]?==?arr2[j]:
res?+=?1
i?+=?1
j?+=?1
elif?arr1[i]?>?arr2[j]:
j?+=?1
else:
i?+=?1
return?res
%timeit?n_common_4(arr1,?arr2)
329?μs?±?12.3?μs?per?loop?(mean?±?std.?dev.?of?7?runs,?1000?loops?each)
5.5 使用更好的數(shù)據(jù)結(jié)構(gòu)
將數(shù)組轉(zhuǎn)為集合,求交集的長度。平均運行時間0.067毫秒。
def?n_common_5(arr1,?arr2):
return?len(set(arr1)?&?set(arr2))
%timeit?n_common_5(arr1,?arr2)
67.2?μs?±?755?ns?per?loop?(mean?±?std.?dev.?of?7?runs,?10000?loops?each)
總結(jié)
以上是生活随笔為你收集整理的python写算法太慢_程序运行慢?你怕是写的假 Python的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 简单小程序代码_开个小程序店铺需要多少钱
- 下一篇: 远程控制木马软件_Jump Deskto