「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > Python プログラミングの最適化テクニック。

Python プログラミングの最適化テクニック。

2024 年 8 月 25 日に公開
ブラウズ:492

Python programming optimisation techniques.

最適化されたコードはソフトウェアの効率、パフォーマンス、スケーラビリティに直接影響するため、不可欠です。適切に記述されたコードは、実行速度が速く、消費リソースが少なく、保守性が高いため、より大きなワークロードを処理し、ユーザー エクスペリエンスを向上させるのに適しています。また、効率的なコードには必要な処理能力とメモリが少なくなるため、運用コストも削減されます。これは、組み込みシステムや大規模なクラウド アプリケーションなど、リソースが限られている環境では特に重要です。

一方、コードの書き方が不十分だと、実行時間が遅くなり、エネルギー消費が増加し、インフラストラクチャ コストが増加する可能性があります。たとえば、Web アプリケーションでは、非効率なコードによりページの読み込みが遅くなり、ユーザー エクスペリエンスが低下し、ユーザーが離れていく可能性があります。データ処理タスクでは、非効率的なアルゴリズムにより大規模なデータセットの処理時間が大幅に増加し、重要な洞察や意思決定が遅れる可能性があります。

さらに、最適化されたコードは多くの場合、保守や拡張がより簡単になります。最適化のベスト プラクティスに従うことで、開発者はコードベースをクリーンでモジュール化した状態に保つことができ、必要に応じてアプリケーションを更新したり拡張したりすることが容易になります。ソフトウェア プロジェクトが複雑になり、システムへの要求が増大するにつれて、これはますます重要になります。

より効率的でパフォーマンスの高いコードを作成するのに役立つ 10 の Python プログラミング最適化テクニックを見てみましょう。これらの手法は、パフォーマンス要件を満たしながら、長期間にわたって拡張性と保守性を維持できる堅牢なアプリケーションを開発するために不可欠です。これらのテクニックは、ベスト プラクティスに従うことで他のプログラミング言語にも適用できます。

1. バリアブルパッキング

変数パッキングは、複数のデータ項目を 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 のドット関数が行列演算用に強化されており、純粋な Python のネストされたループよりもはるかにパフォーマンスが優れています。

7. 短絡条件

ショートサーキットにより不必要な評価が削減されます。これは、複雑な条件チェックやリソースを大量に消費する操作を伴う場合に特に役立ちます。チェックする必要のない条件の実行を防ぎ、時間と計算能力の両方を節約します。
条件チェックは、条件を満たす最初の値が見つかった時点で停止するため、条件を検証または無効にする可能性が最も高い変数を最初に配置する必要があります。 OR 条件 (or) では、真である可能性が最も高い変数を最初に配置しようとし、AND 条件 (and) では、偽である可能性が最も高い変数を最初に配置しようとします。その変数がチェックされるとすぐに、他の値をチェックすることなく条件を終了できます。

例:

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

この例では、Python の論理演算子により、x がゼロ以外の場合にのみ除算が実行され、潜在的なランタイム エラーや不要な計算が防止されます。

8. メモリを解放する

長時間実行されるアプリケーション、特に大規模なデータセットを扱うアプリケーションでは、不要になったメモリを解放することが不可欠です。これは、del、gc.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

短いエラー メッセージは、IoT デバイスや高頻度取引システムなど、リソース効率が重要な環境で役立ちます。

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 やその他のプログラミング言語プログラムをより高速に実行し、メモリの使用量を減らし、スケーラビリティを高めることができます。これは、データ サイエンス、ウェブ、システム プログラミングのアプリケーションにとって特に重要です。

追記: https://perfpy.com/#/ を使用して Python コードの効率をチェックできます。

リリースステートメント この記事は次の場所に転載されています: https://dev.to/jamesbright/10-python-programming-optimisation-techniques-5ckf?1 侵害がある場合は、[email protected] に連絡して削除してください。
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3