defmain(): size = 1000000 for i in range(size): demo_instance = DemoClass(size) value = demo_instance.value demo_instance.value = i
main()
4. 避免數(shù)據(jù)復(fù)制
4.1 避免無意義的數(shù)據(jù)復(fù)制
# 不推薦寫法,代碼耗時:6.5秒 defmain(): size = 10000 for _ in range(size): value = range(size) value_list = [x for x in value] square_list = [x * x for x in value_list]
defmain(): string_list = list(string.ascii_letters * 100) for _ in range(10000): result = concatString(string_list)
main()
5. 利用if條件的短路特性
# 不推薦寫法,代碼耗時:0.05秒 from typing import List
defconcatString(string_list: List[str]) -> str: abbreviations = {'cf.', 'e.g.', 'ex.', 'etc.', 'flg.', 'i.e.', 'Mr.', 'vs.'} abbr_count = 0 result = '' for str_i in string_list: if str_i in abbreviations: result += str_i return result
defmain(): for _ in range(10000): string_list = ['Mr.', 'Hat', 'is', 'Chasing', 'the', 'black', 'cat', '.'] result = concatString(string_list)
main()
if 條件的短路特性是指對if a and b這樣的語句, 當(dāng)a為False時將直接返回,不再計(jì)算b;對于if a or b這樣的語句,當(dāng)a為True時將直接返回,不再計(jì)算b。因此, 為了節(jié)約運(yùn)行時間,對于or語句,應(yīng)該將值為True可能性比較高的變量寫在or前,而and應(yīng)該推后。
# 推薦寫法,代碼耗時:0.03秒 from typing import List
defconcatString(string_list: List[str]) -> str: abbreviations = {'cf.', 'e.g.', 'ex.', 'etc.', 'flg.', 'i.e.', 'Mr.', 'vs.'} abbr_count = 0 result = '' for str_i in string_list: if str_i[-1] == '.'and str_i in abbreviations: # 利用 if 條件的短路特性 result += str_i return result
defmain(): for _ in range(10000): string_list = ['Mr.', 'Hat', 'is', 'Chasing', 'the', 'black', 'cat', '.'] result = concatString(string_list)
main()
6. 循環(huán)優(yōu)化
6.1 用for循環(huán)代替while循環(huán)
# 不推薦寫法。代碼耗時:6.7秒 defcomputeSum(size: int) -> int: sum_ = 0 i = 0 while i < size: sum_ += i i += 1 return sum_
defmain(): size = 10000 for _ in range(size): sum_ = computeSum(size)
main()
Python 的for循環(huán)比while循環(huán)快不少。
# 推薦寫法。代碼耗時:4.3秒 defcomputeSum(size: int) -> int: sum_ = 0 for i in range(size): # for 循環(huán)代替 while 循環(huán) sum_ += i return sum_
defmain(): size = 10000 for _ in range(size): sum_ = computeSum(size)
main()
6.2 使用隱式for循環(huán)代替顯式for循環(huán)
針對上面的例子,更進(jìn)一步可以用隱式for循環(huán)來替代顯式for循環(huán)
# 推薦寫法。代碼耗時:1.7秒 defcomputeSum(size: int) -> int: return sum(range(size)) # 隱式 for 循環(huán)代替顯式 for 循環(huán)
defmain(): size = 10000 for _ in range(size): sum = computeSum(size)
main()
6.3 減少內(nèi)層for循環(huán)的計(jì)算
# 不推薦寫法。代碼耗時:12.8秒 import math
defmain(): size = 10000 sqrt = math.sqrt for x in range(size): for y in range(size): z = sqrt(x) + sqrt(y)
defmain(): size = 10000 sqrt = math.sqrt for x in range(size): sqrt_x = sqrt(x) # 減少內(nèi)層 for 循環(huán)的計(jì)算 for y in range(size): z = sqrt_x + sqrt(y)
@numba.jit defcomputeSum(size: float) -> int: sum = 0 for i in range(size): sum += i return sum
defmain(): size = 10000 for _ in range(size): sum = computeSum(size)
main()
8. 選擇合適的數(shù)據(jù)結(jié)構(gòu)
Python 內(nèi)置的數(shù)據(jù)結(jié)構(gòu)如str, tuple, list, set, dict底層都是 C 實(shí)現(xiàn)的,速度非常快,自己實(shí)現(xiàn)新的數(shù)據(jù)結(jié)構(gòu)想在性能上達(dá)到內(nèi)置的速度幾乎是不可能的。
list類似于 C++ 中的std::vector,是一種動態(tài)數(shù)組。其會預(yù)分配一定內(nèi)存空間,當(dāng)預(yù)分配的內(nèi)存空間用完,又繼續(xù)向其中添加元素時,會申請一塊更大的內(nèi)存空間,然后將原有的所有元素都復(fù)制過去,之后銷毀之前的內(nèi)存空間,再插入新元素。刪除元素時操作類似,當(dāng)已使用內(nèi)存空間比預(yù)分配內(nèi)存空間的一半還少時,會另外申請一塊小內(nèi)存,做一次元素復(fù)制,之后銷毀原有大內(nèi)存空間。因此,如果有頻繁的新增、刪除操作,新增、刪除的元素?cái)?shù)量又很多時,list的效率不高。此時,應(yīng)該考慮使用collections.deque。collections.deque是雙端隊(duì)列,同時具備棧和隊(duì)列的特性,能夠在兩端進(jìn)行 O(1)復(fù)雜度的插入和刪除操作。