優化的程式碼至關重要,因為它直接影響軟體的效率、效能和可擴展性。編寫良好的程式碼執行速度更快,消耗的資源更少,並且更易於維護,使其更適合處理更大的工作負載並改善用戶體驗。它還降低了營運成本,因為高效的程式碼需要更少的處理能力和內存,這在資源有限的環境中尤其重要,例如嵌入式系統或大規模雲端應用程式。

另一方面,編寫不好的程式碼可能會導致執行時間變慢、能源消耗增加以及基礎設施成本更高。例如,在 Web 應用程式中,低效的程式碼可能會減慢頁面載入速度,導致使用者體驗不佳,並可能導致使用者流失。在資料處理任務中,低效的演算法會顯著增加處理大型資料集所需的時間,從而延遲關鍵的見解和決策。

此外,優化的程式碼通常更容易維護和擴展。透過遵循優化最佳實踐,開發人員可以確保其程式碼庫保持乾淨和模組化,從而更輕鬆地根據需要更新或擴展應用程式。隨著軟體專案複雜性的增加以及對系統的需求的增加,這一點變得越來越重要。

讓我們來探索 10 種可以幫助您編寫更有效率、效能更佳的 Python 程式優化技術。這些技術對於開發滿足效能要求同時保持可擴展性和可維護性的強大應用程式至關重要。透過遵循最佳實踐,這些技術也可以應用於其他程式語言。

1.可變包裝

變數打包透過將多個資料項分組到單一結構中來最大限度地減少記憶體使用。在記憶體存取時間顯著影響效能的場景(例如大規模資料處理)中,此技術至關重要。當相關資料打包在一起時,可以更有效地使用 CPU 緩存,從而加快資料檢索速度。

例子:

import struct

# Packing two integers into a binary format
packed_data = struct.pack('ii', 10, 20)

# Unpacking the packed binary data
a, b = struct.unpack('ii', packed_data)

在此範例中,使用struct模組將整數打包為緊湊的二進位格式,使資料處理更加有效率。

2.存儲與內存

了解儲存(磁碟)和記憶體(RAM)之間的差異至關重要。記憶體操作速度更快,但易失性,而儲存是持久的,但速度較慢。在效能關鍵型應用程式中,將頻繁存取的資料保留在記憶體中並最大限度地減少儲存 I/O 對於速度至關重要。

例子:

import mmap

# Memory-mapping a file
with open("data.txt", "r+b") as f:
    mmapped_file = mmap.mmap(f.fileno(), 0)
    print(mmapped_file.readline())
    mmapped_file.close()

內存映射檔案可讓您將磁碟儲存視為內存,從而加快大檔案的存取時間。

3.固定長度與可變長度變數

固定長度變數儲存在連續的記憶體區塊中,從而使存取和操作更快。另一方面,可變長度變數需要額外的開銷來管理動態記憶體分配,這可能會減慢操作速度,特別是在即時系統中。

例子:

import array

# Using fixed-length array for performance
fixed_array = array.array('i', [1, 2, 3, 4, 5])

# Dynamic list (variable-length)
dynamic_list = [1, 2, 3, 4, 5]

這裡, array.array提供了一個固定長度的陣列,提供比動態清單更可預測的效能。

4.內部職能與公共職能

內部函數是那些僅在定義它們的模組內使用的函數,通常會針對速度和效率進行最佳化。公共函數公開供外部使用,並且可能包括額外的錯誤處理或日誌記錄,這使得它們的效率稍低。

例子:

def _private_function(data):
    # Optimized for internal use, with minimal error handling
    return data ** 2

def public_function(data):
    # Includes additional checks for external use
    if isinstance(data, int):
        return _private_function(data)
    raise ValueError("Input must be an integer")

透過將繁重的運算保留在私有函數中,您可以優化程式碼的效率,並保留公用函數以實現外部安全性和可用性。

5.功能修飾符

在 Python 中,裝飾器充當函數修飾符,可讓您在函數主執行之前或之後加入功能。這對於快取、存取控製或日誌記錄等任務很有用,可以優化多個函數呼叫的資源使用。

例子:

from functools import lru_cache

@lru_cache(maxsize=100)
def compute_heavy_function(x):
    # A computationally expensive operation
    return x ** x

使用lru_cache作為裝飾器可以快取昂貴的函數呼叫的結果,透過避免冗餘計算來提高效能。

6.使用庫

利用函式庫可以讓您避免重新發明輪子。像 NumPy 這樣的函式庫是用 C 語言編寫的,並且是為了效能而建構的,與純 Python 實作相比,它們對於繁重的數值計算來說更有效率。

例子:

import numpy as np

# Efficient matrix multiplication using NumPy
matrix_a = np.random.rand(1000, 1000)
matrix_b = np.random.rand(1000, 1000)
result = np.dot(matrix_a, matrix_b)

在這裡,NumPy 的dot函數針對矩陣運算進行了增強,遠優於純 Python 中的巢狀循環。

7.短路條件

短路減少了不必要的評估,這在複雜的條件檢查或涉及資源密集型操作時特別有價值。它可以防止執行不需要檢查的條件,從而節省時間和計算能力。

由於條件檢查將在找到滿足條件的第一個值時停止,因此您應該先放置最有可能驗證/無效條件的變數。在 OR 條件(or)中,嘗試將最可能為 true 的變數放在前面,而在 AND 條件(and)中,嘗試將最可能為 false 的變數放在前面。一旦檢查了該變數,條件就可以退出,而無需檢查其他值。

例子:

def complex_condition(x, y):
    return x != 0 and y / x > 2  # Stops evaluation if x is 0

在此範例中,Python 的邏輯運算子確保僅當x非零時才執行除法,從而防止潛在的執行時錯誤和不必要的計算。

8.釋放記憶體

在長時間執行的應用程式中,尤其是那些處理大型資料集的應用程式中,一旦不再需要記憶體就必須釋放記憶體。這可以使用delgc.collect()或允許物件超出範圍來完成。

例子:

import gc

# Manual garbage collection to free up memory
large_data = [i for i in range(1000000)]
del large_data
gc.collect()  # Forces garbage collection

使用gc.collect()可確保及時回收內存,這在內存受限的環境中至關重要。

9.簡短的錯誤訊息

在記憶體或頻寬有限的系統中,例如嵌入式系統或分散式應用程式中的日誌記錄,短錯誤訊息可以減少開銷。這種做法也適用於需要大規模錯誤日誌記錄的場景。

例子:

try:
    result = 10 / 0
except ZeroDivisionError:
    print("Err: Div/0")  # Short, concise error message

短錯誤訊息在資源效率至關重要的環境中非常有用,例如物聯網設備或高頻交易系統。

10.優化循環

循環是效率低下的常見原因,尤其是在處理大型資料集時。透過減少迭代、簡化邏輯或使用向量化運算來優化循環可以顯著提高效能。

例子:

import numpy as np

# Vectorised operation with NumPy
array = np.array([1, 2, 3, 4, 5])

# Instead of looping through elements
result = array * 2  # Efficient, vectorised operation

向量化消除了對顯式循環的需要,利用低階優化來加快執行速度。


透過應用這些技術,您可以確保您的 Python 或其他程式語言程式執行得更快、使用更少的記憶體並且更具可擴展性,這對於資料科學、Web 和系統程式設計中的應用程式尤其重要。

PS:您可以使用https://perfpy.com/#/來檢查python程式碼效率。


原文出處:https://dev.to/jamesbright/10-python-programming-optimisation-techniques-5ckf


共有 0 則留言