国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

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

3天內不再提示

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

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

掃碼添加小助手

加入工程師交流群

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

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

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

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

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

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 語言寫一些簡單的腳本,當編寫腳本時,通常習慣了直接將其寫為全局變量,例如上面的代碼。但是,由于全局變量和局部變量實現方式不同,定義在全局范圍內的代碼運行速度會比定義在函數中的慢不少。通過將腳本語句放入到函數中,通常可帶來 15% - 30% 的速度提升。

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

import math

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

size = 10000

for x in range(size):

for y in range(size):

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

main()

2. 避免.2.1 避免模塊和函數屬性訪問

# 不推薦寫法。代碼耗時: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()

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

# 第一次優化寫法。代碼耗時: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 節中我們講到,局部變量的查找會比全局變量更快,因此對于頻繁訪問的變量sqrt,通過將其改為局部變量可以加速運行。

# 第二次優化寫法。代碼耗時: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函數中還有。的存在,那就是調用list的append方法。通過將該方法賦值給一個局部變量,可以徹底消除computeSqrt函數中for循環內部的。使用。

# 推薦寫法。代碼耗時: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 避免類內屬性訪問# 不推薦寫法。代碼耗時: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()

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

# 推薦寫法。代碼耗時: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函數對屬性進行訪問通常是 C/C++ 程序員遺留下來的代碼風格。如果真的沒有必要,就使用簡單屬性。

# 推薦寫法,代碼耗時: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. 避免數據復制4.1 避免無意義的數據復制

# 不推薦寫法,代碼耗時: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完全沒有必要,這會創建不必要的數據結構或復制。

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

def main():

size = 10000

for _ in range(size):

value = range(size)

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

main()

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

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

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

def main():

size = 1000000

for _ in range(size):

a = 3

b = 5

temp = a

a = b

b = temp

main()

上面的代碼在交換值時創建了一個臨時變量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 中字符串是不可變對象,其會申請一塊內存空間,將a和b分別復制到該新申請的內存空間中。因此,如果要拼接 n 個字符串,會產生 n-1 個中間結果,每產生一個中間結果都需要申請和復制一次內存,嚴重影響運行效率。

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

# 推薦寫法,代碼耗時: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’, ‘。’]

result = concatString(string_list)

main()

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

# 推薦寫法,代碼耗時: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’, ‘。’]

result = concatString(string_list)

main()

6. 循環優化6.1 用for循環代替while循環

# 不推薦寫法。代碼耗時: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循環比while循環快不少。

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

def computeSum(size: int) -》 int:

sum_ = 0

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

sum_ += i

return sum_

def main():

size = 10000

for _ in range(size):

sum_ = computeSum(size)

main()

6.2 使用隱式for循環代替顯式for循環

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

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

def computeSum(size: int) -》 int:

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

def main():

size = 10000

for _ in range(size):

sum = computeSum(size)

main()

6.3 減少內層for循環的計算

# 不推薦寫法。代碼耗時: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)位于內側for循環, 每次訓練過程中都會重新計算一次,增加了時間開銷。

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

import math

def main():

size = 10000

sqrt = math.sqrt

for x in range(size):

sqrt_x = sqrt(x) # 減少內層 for 循環的計算

for y in range(size):

z = sqrt_x + sqrt(y)

main()

7. 使用numba.jit我們沿用上面介紹過的例子,在此基礎上使用numba.jit。numba可以將 Python 函數 JIT 編譯為機器碼執行,大大提高代碼運行速度。關于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. 選擇合適的數據結構Python 內置的數據結構如str, tuple, list, set, dict底層都是 C 實現的,速度非常快,自己實現新的數據結構想在性能上達到內置的速度幾乎是不可能的。

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

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

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

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

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

下面的網頁給出了常用的 Python 數據結構的各項操作的時間復雜度:https://wiki.python.org/moin/TimeComplexity

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

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

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C++
    C++
    +關注

    關注

    22

    文章

    2123

    瀏覽量

    77110
  • 代碼
    +關注

    關注

    30

    文章

    4967

    瀏覽量

    73954
  • 編譯
    +關注

    關注

    0

    文章

    694

    瀏覽量

    35157
  • python
    +關注

    關注

    57

    文章

    4876

    瀏覽量

    90022

原文標題:Python 優化提速的 8 個小技巧

文章出處:【微信號:harmonyos_developer,微信公眾號:harmonyos_developer】歡迎添加關注!文章轉載請注明出處。

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

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    1688 商品詳情 API 調用與數據解析 Python 實戰

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

    Python運行本地Web服務并實現遠程訪問

    本文介紹使用Python搭建本地Web服務并結合 ZeroNews 實現公網訪問。
    的頭像 發表于 02-06 11:39 ?148次閱讀
    <b class='flag-5'>Python</b><b class='flag-5'>運行</b>本地Web服務并實現遠程訪問

    沒有專利的opencv-python 版本

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

    Termux中調試圣誕樹Python代碼

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

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

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

    代碼如何重塑硬件設計,AI如何加速創新?

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

    termux調試python猜數字游戲

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

    termux如何搭建python游戲

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

    python app不能運行怎么解決?

    我使用helloword的模板,上傳了IG502,但不能運行,請大神幫忙。系統日志如下:sntpc[1226]: ntp request error: 113, No route to host
    發表于 08-06 06:27

    RAKsmart企業服務器上部署DeepSeek編寫運行代碼

    在RAKsmart企業服務器上部署并運行DeepSeek模型的代碼示例和詳細步驟。假設使用 Python + Transformers庫 + FastAPI實現一個基礎的AI服務。主機推薦小編為您整理發布RAKsmart企業服務
    的頭像 發表于 03-25 10:39 ?697次閱讀

    零基礎入門:如何在樹莓派上編寫和運行Python程序?

    在這篇文章中,我將為你簡要介紹Python程序是什么、Python程序可以用來做什么,以及如何在RaspberryPi上編寫和運行一個簡單的Python程序。什么是
    的頭像 發表于 03-25 09:27 ?2026次閱讀
    零基礎入門:如何在樹莓派上編寫和<b class='flag-5'>運行</b><b class='flag-5'>Python</b>程序?

    請問是否可以使用單個輸入圖像運行人臉檢測MTCNN Python演示?

    是否可以使用單個輸入圖像運行人臉檢測 MTCNN Python* 演示?
    發表于 03-06 08:15

    創建了用于OpenVINO?推理的自定義C++和Python代碼,從C++代碼中獲得的結果與Python代碼不同是為什么?

    創建了用于OpenVINO?推理的自定義 C++ 和 Python* 代碼。 在兩個推理過程中使用相同的圖像和模型。 從 C++ 代碼中獲得的結果與 Python*
    發表于 03-06 06:22

    是否可以使用OpenVINO?部署管理器在部署機器上運行Python應用程序?

    使用 OpenVINO?部署管理器創建運行時軟件包。 將運行時包轉移到部署機器中。 無法確定是否可以在部署機器上運行 Python 應用程序,而無需安裝OpenVINO? Toolk
    發表于 03-05 08:16

    運行OVModelForCausalLM Python模塊時出錯了,怎么解決?

    創建了一個自定義 Python* 代碼,類似于遵循 240-dolly-2-instruction 的 Jupyter 筆記本。 OVModelForCausalLM Python* 模塊
    發表于 03-05 06:44