日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Python 代碼加速運行的的小技巧

5jek_harmonyos ? 來源:博客園 ? 作者: 始終不夠啊 ? 2021-09-01 11:28 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

Python 是一種腳本語言,相比 C/C++ 這樣的編譯語言,在效率和性能方面存在一些不足。但是,有很多時候,Python 的效率并沒有想象中的那么夸張。本文對一些 Python 代碼加速運行的技巧進行整理。

0. 代碼優(yōu)化原則本文會介紹不少的 Python 代碼加速運行的技巧。在深入代碼優(yōu)化細節(jié)之前,需要了解一些代碼優(yōu)化基本原則。

第一個基本原則是不要過早優(yōu)化。很多人一開始寫代碼就奔著性能優(yōu)化的目標,“讓正確的程序更快要比讓快速的程序正確容易得多”。因此,優(yōu)化的前提是代碼能正常工作。過早地進行優(yōu)化可能會忽視對總體性能指標的把握,在得到全局結(jié)果前不要主次顛倒。

第二個基本原則是權(quán)衡優(yōu)化的代價。優(yōu)化是有代價的,想解決所有性能的問題是幾乎不可能的。通常面臨的選擇是時間換空間或空間換時間。另外,開發(fā)代價也需要考慮。

第三個原則是不要優(yōu)化那些無關(guān)緊要的部分。如果對代碼的每一部分都去優(yōu)化,這些修改會使代碼難以閱讀和理解。如果你的代碼運行速度很慢,首先要找到代碼運行慢的位置,通常是內(nèi)部循環(huán),專注于運行慢的地方進行優(yōu)化。在其他地方,一點時間上的損失沒有什么影響。

1. 避免全局變量# 不推薦寫法。代碼耗時:26.8秒

import math

size = 10000

for x in range(size):

for y in range(size):

z = math.sqrt(x) + math.sqrt(y)

許多程序員剛開始會用 Python 語言寫一些簡單的腳本,當編寫腳本時,通常習(xí)慣了直接將其寫為全局變量,例如上面的代碼。但是,由于全局變量和局部變量實現(xiàn)方式不同,定義在全局范圍內(nèi)的代碼運行速度會比定義在函數(shù)中的慢不少。通過將腳本語句放入到函數(shù)中,通常可帶來 15% - 30% 的速度提升。

# 推薦寫法。代碼耗時:20.6秒

import math

def main(): # 定義到函數(shù)中,以減少全部變量使用

size = 10000

for x in range(size):

for y in range(size):

z = math.sqrt(x) + math.sqrt(y)

main()

2. 避免.2.1 避免模塊和函數(shù)屬性訪問

# 不推薦寫法。代碼耗時:14.5秒

import math

def computeSqrt(size: int):

result = []

for i in range(size):

result.append(math.sqrt(i))

return result

def main():

size = 10000

for _ in range(size):

result = computeSqrt(size)

main()

每次使用。(屬性訪問操作符時)會觸發(fā)特定的方法,如__getattribute__()和__getattr__(),這些方法會進行字典操作,因此會帶來額外的時間開銷。通過from import語句,可以消除屬性訪問。

# 第一次優(yōu)化寫法。代碼耗時:10.9秒

from math import sqrt

def computeSqrt(size: int):

result = []

for i in range(size):

result.append(sqrt(i)) # 避免math.sqrt的使用

return result

def main():

size = 10000

for _ in range(size):

result = computeSqrt(size)

main()

在第 1 節(jié)中我們講到,局部變量的查找會比全局變量更快,因此對于頻繁訪問的變量sqrt,通過將其改為局部變量可以加速運行。

# 第二次優(yōu)化寫法。代碼耗時:9.9秒

import math

def computeSqrt(size: int):

result = []

sqrt = math.sqrt # 賦值給局部變量

for i in range(size):

result.append(sqrt(i)) # 避免math.sqrt的使用

return result

def main():

size = 10000

for _ in range(size):

result = computeSqrt(size)

main()

除了math.sqrt外,computeSqrt函數(shù)中還有。的存在,那就是調(diào)用list的append方法。通過將該方法賦值給一個局部變量,可以徹底消除computeSqrt函數(shù)中for循環(huán)內(nèi)部的。使用。

# 推薦寫法。代碼耗時:7.9秒

import math

def computeSqrt(size: int):

result = []

append = result.append

sqrt = math.sqrt # 賦值給局部變量

for i in range(size):

append(sqrt(i)) # 避免 result.append 和 math.sqrt 的使用

return result

def main():

size = 10000

for _ in range(size):

result = computeSqrt(size)

main()

2.2 避免類內(nèi)屬性訪問# 不推薦寫法。代碼耗時:10.4秒

import math

from typing import List

class DemoClass:

def __init__(self, value: int):

self._value = value

def computeSqrt(self, size: int) -》 List[float]:

result = []

append = result.append

sqrt = math.sqrt

for _ in range(size):

append(sqrt(self._value))

return result

def main():

size = 10000

for _ in range(size):

demo_instance = DemoClass(size)

result = demo_instance.computeSqrt(size)

main()

避免。的原則也適用于類內(nèi)屬性,訪問self._value的速度會比訪問一個局部變量更慢一些。通過將需要頻繁訪問的類內(nèi)屬性賦值給一個局部變量,可以提升代碼運行速度。

# 推薦寫法。代碼耗時:8.0秒

import math

from typing import List

class DemoClass:

def __init__(self, value: int):

self._value = value

def computeSqrt(self, size: int) -》 List[float]:

result = []

append = result.append

sqrt = math.sqrt

value = self._value

for _ in range(size):

append(sqrt(value)) # 避免 self._value 的使用

return result

def main():

size = 10000

for _ in range(size):

demo_instance = DemoClass(size)

demo_instance.computeSqrt(size)

main()

3. 避免不必要的抽象# 不推薦寫法,代碼耗時:0.55秒

class DemoClass:

def __init__(self, value: int):

self.value = value

@property

def value(self) -》 int:

return self._value

@value.setter

def value(self, x: int):

self._value = x

def main():

size = 1000000

for i in range(size):

demo_instance = DemoClass(size)

value = demo_instance.value

demo_instance.value = i

main()

任何時候當你使用額外的處理層(比如裝飾器、屬性訪問、描述器)去包裝代碼時,都會讓代碼變慢。大部分情況下,需要重新進行審視使用屬性訪問器的定義是否有必要,使用getter/setter函數(shù)對屬性進行訪問通常是 C/C++ 程序員遺留下來的代碼風(fēng)格。如果真的沒有必要,就使用簡單屬性。

# 推薦寫法,代碼耗時:0.33秒

class DemoClass:

def __init__(self, value: int):

self.value = value # 避免不必要的屬性訪問器

def main():

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秒

def main():

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]

main()

上面的代碼中value_list完全沒有必要,這會創(chuàng)建不必要的數(shù)據(jù)結(jié)構(gòu)或復(fù)制。

# 推薦寫法,代碼耗時:4.8秒

def main():

size = 10000

for _ in range(size):

value = range(size)

square_list = [x * x for x in value] # 避免無意義的復(fù)制

main()

另外一種情況是對 Python 的數(shù)據(jù)共享機制過于偏執(zhí),并沒有很好地理解或信任 Python 的內(nèi)存模型,濫用 copy.deepcopy()之類的函數(shù)。通常在這些代碼中是可以去掉復(fù)制操作的。

4.2 交換值時不使用中間變量

# 不推薦寫法,代碼耗時:0.07秒

def main():

size = 1000000

for _ in range(size):

a = 3

b = 5

temp = a

a = b

b = temp

main()

上面的代碼在交換值時創(chuàng)建了一個臨時變量temp,如果不借助中間變量,代碼更為簡潔、且運行速度更快。

# 推薦寫法,代碼耗時:0.06秒

def main():

size = 1000000

for _ in range(size):

a = 3

b = 5

a, b = b, a # 不借助中間變量

main()

4.3 字符串拼接用join而不是+

# 不推薦寫法,代碼耗時:2.6秒

import string

from typing import List

def concatString(string_list: List[str]) -》 str:

result = ‘’

for str_i in string_list:

result += str_i

return result

def main():

string_list = list(string.ascii_letters * 100)

for _ in range(10000):

result = concatString(string_list)

main()

當使用a + b拼接字符串時,由于 Python 中字符串是不可變對象,其會申請一塊內(nèi)存空間,將a和b分別復(fù)制到該新申請的內(nèi)存空間中。因此,如果要拼接 n 個字符串,會產(chǎn)生 n-1 個中間結(jié)果,每產(chǎn)生一個中間結(jié)果都需要申請和復(fù)制一次內(nèi)存,嚴重影響運行效率。

而使用join()拼接字符串時,會首先計算出需要申請的總的內(nèi)存空間,然后一次性地申請所需內(nèi)存,并將每個字符串元素復(fù)制到該內(nèi)存中去。

# 推薦寫法,代碼耗時:0.3秒

import string

from typing import List

def concatString(string_list: List[str]) -》 str:

return ‘’.join(string_list) # 使用 join 而不是 +

def main():

string_list = list(string.ascii_letters * 100)

for _ in range(10000):

result = concatString(string_list)

main()

5. 利用if條件的短路特性# 不推薦寫法,代碼耗時:0.05秒

from typing import List

def concatString(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

def main():

for _ in range(10000):

string_list = [‘Mr.’, ‘Hat’, ‘is’, ‘Chasing’, ‘the’, ‘black’, ‘cat’, ‘?!?/p>

result = concatString(string_list)

main()

if 條件的短路特性是指對if a and b這樣的語句, 當a為False時將直接返回,不再計算b;對于if a or b這樣的語句,當a為True時將直接返回,不再計算b。因此, 為了節(jié)約運行時間,對于or語句,應(yīng)該將值為True可能性比較高的變量寫在or前,而and應(yīng)該推后。

# 推薦寫法,代碼耗時:0.03秒

from typing import List

def concatString(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

def main():

for _ in range(10000):

string_list = [‘Mr.’, ‘Hat’, ‘is’, ‘Chasing’, ‘the’, ‘black’, ‘cat’, ‘?!?/p>

result = concatString(string_list)

main()

6. 循環(huán)優(yōu)化6.1 用for循環(huán)代替while循環(huán)

# 不推薦寫法。代碼耗時:6.7秒

def computeSum(size: int) -》 int:

sum_ = 0

i = 0

while i 《 size:

sum_ += i

i += 1

return sum_

def main():

size = 10000

for _ in range(size):

sum_ = computeSum(size)

main()

Python 的for循環(huán)比while循環(huán)快不少。

# 推薦寫法。代碼耗時:4.3秒

def computeSum(size: int) -》 int:

sum_ = 0

for i in range(size): # for 循環(huán)代替 while 循環(huán)

sum_ += i

return sum_

def main():

size = 10000

for _ in range(size):

sum_ = computeSum(size)

main()

6.2 使用隱式for循環(huán)代替顯式for循環(huán)

針對上面的例子,更進一步可以用隱式for循環(huán)來替代顯式for循環(huán)

# 推薦寫法。代碼耗時:1.7秒

def computeSum(size: int) -》 int:

return sum(range(size)) # 隱式 for 循環(huán)代替顯式 for 循環(huán)

def main():

size = 10000

for _ in range(size):

sum = computeSum(size)

main()

6.3 減少內(nèi)層for循環(huán)的計算

# 不推薦寫法。代碼耗時:12.8秒

import math

def main():

size = 10000

sqrt = math.sqrt

for x in range(size):

for y in range(size):

z = sqrt(x) + sqrt(y)

main()

上面的代碼中sqrt(x)位于內(nèi)側(cè)for循環(huán), 每次訓(xùn)練過程中都會重新計算一次,增加了時間開銷。

# 推薦寫法。代碼耗時:7.0秒

import math

def main():

size = 10000

sqrt = math.sqrt

for x in range(size):

sqrt_x = sqrt(x) # 減少內(nèi)層 for 循環(huán)的計算

for y in range(size):

z = sqrt_x + sqrt(y)

main()

7. 使用numba.jit我們沿用上面介紹過的例子,在此基礎(chǔ)上使用numba.jit。numba可以將 Python 函數(shù) JIT 編譯為機器碼執(zhí)行,大大提高代碼運行速度。關(guān)于numba的更多信息見下面的主頁:http://numba.pydata.org/numba.pydata.org

# 推薦寫法。代碼耗時:0.62秒

import numba

@numba.jit

def computeSum(size: float) -》 int:

sum = 0

for i in range(size):

sum += i

return sum

def main():

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 實現(xiàn)的,速度非??欤约簩崿F(xiàn)新的數(shù)據(jù)結(jié)構(gòu)想在性能上達到內(nèi)置的速度幾乎是不可能的。

list類似于 C++ 中的std::vector,是一種動態(tài)數(shù)組。其會預(yù)分配一定內(nèi)存空間,當預(yù)分配的內(nèi)存空間用完,又繼續(xù)向其中添加元素時,會申請一塊更大的內(nèi)存空間,然后將原有的所有元素都復(fù)制過去,之后銷毀之前的內(nèi)存空間,再插入新元素。

刪除元素時操作類似,當已使用內(nèi)存空間比預(yù)分配內(nèi)存空間的一半還少時,會另外申請一塊小內(nèi)存,做一次元素復(fù)制,之后銷毀原有大內(nèi)存空間。

因此,如果有頻繁的新增、刪除操作,新增、刪除的元素數(shù)量又很多時,list的效率不高。此時,應(yīng)該考慮使用collections.deque。collections.deque是雙端隊列,同時具備棧和隊列的特性,能夠在兩端進行 O(1) 復(fù)雜度的插入和刪除操作。

list的查找操作也非常耗時。當需要在list頻繁查找某些元素,或頻繁有序訪問這些元素時,可以使用bisect維護list對象有序并在其中進行二分查找,提升查找的效率。

另外一個常見需求是查找極小值或極大值,此時可以使用heapq模塊將list轉(zhuǎn)化為一個堆,使得獲取最小值的時間復(fù)雜度是 O(1)。

下面的網(wǎng)頁給出了常用的 Python 數(shù)據(jù)結(jié)構(gòu)的各項操作的時間復(fù)雜度:https://wiki.python.org/moin/TimeComplexity

參考資料David Beazley & Brian K. Jones. Python Cookbook, Third edition. O‘Reilly Media, ISBN: 9781449340377, 2013.

張穎 & 賴勇浩。 編寫高質(zhì)量代碼:改善Python程序的91個建議。 機械工業(yè)出版社, ISBN: 9787111467045, 2014.

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2131

    瀏覽量

    77419
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4977

    瀏覽量

    74419
  • 編譯
    +關(guān)注

    關(guān)注

    0

    文章

    696

    瀏覽量

    35296
  • python
    +關(guān)注

    關(guān)注

    58

    文章

    4889

    瀏覽量

    90330

原文標題:Python 優(yōu)化提速的 8 個小技巧

文章出處:【微信號:harmonyos_developer,微信公眾號:harmonyos_developer】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    STM32N6 在 PSRAM 上運行代碼的調(diào)試

    1. 引言STM32N6 項目中,用戶代碼可能會比較大,此時僅用內(nèi)部 SRAM 并不能滿足用代碼運行需求。那么,將代碼放置到 PSRAM 上運行
    發(fā)表于 04-15 16:02 ?0次下載

    使用PYTHON進行的跨平臺仿真

    應(yīng)用案例,其中我們在一維和二維光柵上執(zhí)行參數(shù)掃描。 使用Python運行VirtualLab Fusion光學(xué)仿真 我們將演示如何使用Python在VirtualLab Fusion中運行
    發(fā)表于 04-02 08:21

    [VirtualLab] 使用Python運行VirtualLab Fusion光學(xué)仿真

    摘要 VirtualLab Fusion允許Python外部訪問其建模技術(shù)、求解器和結(jié)果。這個用例介紹了一種使用路徑變量和Visual Studio代碼Python連接到VirtualLab
    發(fā)表于 03-31 09:39

    如何在 VisionFive 上使用 Python 包?

    VisionFive Fedora 下的本地目錄,請在源代碼目錄下執(zhí)行以下命令: 提示:源代碼可從以下位置下載:愿景五.gpio. sudo yum install python
    發(fā)表于 03-30 08:28

    工作流代碼節(jié)點說明工作流代碼節(jié)點說明

    說明如下: 開發(fā)語言 代碼節(jié)點暫時只支持Python語言。 基于 Python 3.11.4 的標準庫,目前支持的庫有python內(nèi)置的所有庫以及開源選型預(yù)置的三方庫。說明:不支持網(wǎng)絡(luò)
    發(fā)表于 03-26 16:56

    LAT1621_STM32N6 在 PSRAM 上運行代碼的調(diào)試

    STM32N6 項目中,用戶代碼可能會比較大,此時僅用內(nèi)部 SRAM 并不能滿足用代碼運行需求。那么,將代碼放置到 PSRAM 上運行也是個
    發(fā)表于 03-11 10:44 ?0次下載

    1688 商品詳情 API 調(diào)用與數(shù)據(jù)解析 Python 實戰(zhàn)

    你想要的是 1688 商品詳情 API 的 Python 調(diào)用與數(shù)據(jù)解析實戰(zhàn)方案,核心是完成 API 憑證配置、接口請求(含簽名)、響應(yīng)數(shù)據(jù)解析、異常處理 的全流程落地,我會提供可直接運行代碼,并
    的頭像 發(fā)表于 02-10 11:23 ?406次閱讀

    Python運行本地Web服務(wù)并實現(xiàn)遠程訪問

    本文介紹使用Python搭建本地Web服務(wù)并結(jié)合 ZeroNews 實現(xiàn)公網(wǎng)訪問。
    的頭像 發(fā)表于 02-06 11:39 ?373次閱讀
    <b class='flag-5'>Python</b><b class='flag-5'>運行</b>本地Web服務(wù)并實現(xiàn)遠程訪問

    沒有專利的opencv-python 版本

    保留基礎(chǔ)功能,完全免費合規(guī)),支持 Python 3.13 的版本為 4.8.0.74 及以上,安裝命令: # 清華源加速,安裝最新穩(wěn)定版(自動匹配 Python 3.13) pip install
    發(fā)表于 12-13 12:37

    Termux中調(diào)試圣誕樹Python代碼

    在Termux中調(diào)試Python代碼(以圣誕樹立例)非常簡單,核心分為環(huán)境準備、代碼編寫、運行調(diào)試三個步驟,下面一步步教你操作: 一、環(huán)境準備(首次使用需做) Termux默認可能沒有
    發(fā)表于 12-09 09:02

    在極海APM32系列MCU中如何把代碼重定位到SDRAM運行

    在有些情況下,我們想要把代碼放到SDRAM運行。下面介紹在APM32的MCU中,如何把代碼重定位到SDRAM運行。對于不同APM32系列的MCU,方法都是一樣的。
    的頭像 發(fā)表于 11-04 09:14 ?5434次閱讀
    在極海APM32系列MCU中如何把<b class='flag-5'>代碼</b>重定位到SDRAM<b class='flag-5'>運行</b>

    代碼如何重塑硬件設(shè)計,AI如何加速創(chuàng)新?

    “ ?TS Circuit 創(chuàng)始人 Sebe 與 Atopile 創(chuàng)始人 Matt 之間非常有意思的一段對話,討論了代碼如何重塑硬件設(shè)計及 AI 如何加速創(chuàng)新。非常值得完整的聽一遍,用中文重塑了對話
    的頭像 發(fā)表于 09-06 11:19 ?937次閱讀

    termux調(diào)試python猜數(shù)字游戲

    支持的核心語言,安裝簡單且運行高效。 2. 創(chuàng)建腳本文件 ```bash nano guess_number.py# 使用Termux內(nèi)置nano編輯器 ``` --- ? 二、游戲代碼
    發(fā)表于 08-29 17:15

    termux如何搭建python游戲

    用VS Code編輯 - 版本控制:`git`管理代碼,同步至GitHub/Gitee - 任務(wù)調(diào)度:通過`crontab`設(shè)置定時測試(如每分鐘運行游戲腳本:`*/1 * * * * python
    發(fā)表于 08-29 07:06

    python app不能運行怎么解決?

    我使用helloword的模板,上傳了IG502,但不能運行,請大神幫忙。系統(tǒng)日志如下:sntpc[1226]: ntp request error: 113, No route to host
    發(fā)表于 08-06 06:27
    阿拉尔市| 田林县| 兴文县| 阳江市| 新晃| 梓潼县| 平利县| 商河县| 仙居县| 柳河县| 泸水县| 天柱县| 固原市| 陵水| 鲁甸县| 新丰县| 汉源县| 莱州市| 南涧| 桂林市| 永定县| 海城市| 内丘县| 泉州市| 时尚| 虎林市| 兴宁市| 台州市| 新邵县| 光泽县| 泾川县| 蛟河市| 会理县| 阿图什市| 绥芬河市| 台江县| 马边| 大邑县| 思茅市| 霍城县| 万全县|