Python スクリプトを最適化してパフォーマンスを向上させる方法

Python Sukuriputowo Zui Shi Huashitepafomansuwo Xiang Shangsaseru Fang Fa



パフォーマンスを向上させるために Python スクリプトを最適化するには、コード内のボトルネックを特定して対処し、コードをより高速かつ効率的に実行できるようにする必要があります。 Python は、人気があり強力なプログラミング言語であり、現在、データ分析、ML プロジェクト (機械学習)、Web 開発などを含む数多くのアプリケーションで使用されています。 Python コードの最適化は、より少ないコード行、より少ないメモリ、または追加のリソースを使用してアクティビティを実行する際に、開発者プログラムの速度と効率を向上させる戦略です。コードが大きく非効率的であると、プログラムの速度が低下し、クライアントの満足度が低下したり、経済的損失が発生したり、修正やトラブルシューティングにさらに多くの作業が必要になったりする可能性があります。

これは、複数のアクションまたはデータの処理を必要とするタスクを実行するときに必要です。したがって、一部の非効率なコード ブロックや機能を切り替えて強化すると、次のような素晴らしい結果が得られる可能性があります。

  1. アプリケーションのパフォーマンスを向上させる
  2. 読みやすく整理されたコードを作成する
  3. エラーの監視とデバッグを簡素化する
  4. かなりの計算能力などを節約する

コードのプロファイルを作成する

最適化を開始する前に、プロジェクト コードの速度を低下させている部分を特定することが重要です。 Python でプロファイリングするための手法には、cProfile パッケージとプロファイル パッケージが含まれます。このようなツールを利用して、特定の関数やコード行の実行速度を測定します。 cProfile モジュールは、各スクリプト関数の実行にかかる時間を詳細に示すレポートを生成します。このレポートは、実行速度が遅い機能を見つけて改善するのに役立ちます。







コードスニペット:



輸入 cプロフィール として cP
確かに 合計を計算する ( 入力番号 ) :
入力数値の合計 = 0
その間 入力番号 > 0 :
入力数値の合計 + = inputNumber % 10
inputNumber // = 10
印刷する ( 「入力数値のすべての桁の合計は次のとおりです: 'sum_of_input_numbers'」 )
戻る 入力数値の合計
確かに メイン機能 ( ) :
cP. 走る ( '計算合計(9876543789)' )
もし __名前__ == '__主要__' :
メイン機能 ( )

出力の最初の行に見られるように、プログラムは合計 5 つの関数呼び出しを行います。各関数呼び出しの詳細は、次の数行に表示されます。これには、関数が呼び出された回数、関数の全体的な時間、呼び出しごとの時間、および関数の全体的な時間 (含む) が含まれます。呼び出されるすべての関数)。



さらに、プログラムは、プログラムがすべてのタスクの実行時間を 0.000 秒以内に完了したことを示すレポートをプロンプト画面に印刷します。これはプログラムがどれほど速いかを示しています。





適切なデータ構造を選択する

パフォーマンス特性はデータ構造に依存します。特に、汎用ストレージに関しては、リストよりも辞書の方が検索が高速です。データに対して実行する操作に最も適したデータ構造がわかっている場合は、それを選択します。次の例では、データ構造内の要素が存在するかどうかを判断するために、同一のプロセスに対する異なるデータ構造の有効性を調査します。



リスト、セット、辞書の各データ構造に要素が存在するかどうかを確認するのにかかる時間を評価し、それらを比較します。

OptimizeDataType.py:

輸入 タイメイ として って
輸入 ランダム として ロンドブジ
# 整数のリストを生成する
ランダムデータリスト = [ ロンドブジェ。 ランディント ( 1 10000 ) のために _ 範囲 ( 10000 )
# 同じデータからセットを作成する
ランダムデータセット = セット ( ランダムデータリスト )

# 同じデータをキーとする辞書を作成する
obj_DataDictionary = { 1 つ目: なし のために 1つで ランダムデータリスト }

# 検索する要素(データ内に存在)
検索するランダムな数 = ロンドブジェ。 選択 ( ランダムデータリスト )

# リスト内のメンバーシップを確認する時間を測定する
リスト時間 = って。 タイメイ ( ラムダ : 検索するランダムな番号 ランダムデータリスト 番号 = 1000 )

# セット内のメンバーシップを確認する時間を測定する
set_time = って。 タイメイ ( ラムダ : 検索するランダムな番号 ランダムデータセット 番号 = 1000 )

# 辞書のメンバーシップをチェックする時間を測定する
dict_time = って。 タイメイ ( ラムダ : 検索するランダムな番号 obj_DataDictionary 番号 = 1000 )

印刷する ( f 「リストのメンバーシップのチェック時間: {list_time:.6f} 秒」 )
印刷する ( f 「メンバーシップチェック時間を設定します: {set_time:.6f} 秒」 )
印刷する ( f 「辞書メンバーシップのチェック時間: {dict_time:.6f} 秒」 )

このコードは、メンバーシップ チェックを実行する際のリスト、セット、およびディクショナリのパフォーマンスを比較します。一般に、セットと辞書はハッシュ ベースの検索を使用するため、メンバーシップ テストではリストよりも大幅に高速であり、平均時間計算量は O(1) です。一方、リストは線形検索を実行する必要があるため、メンバーシップ テストの計算量は O(n) になります。

  コンピュータのスクリーンショット 自動生成された説明

ループの代わりに組み込み関数を使用する

Python の多数の組み込み関数またはメソッドを使用して、フィルタリング、並べ替え、マッピングなどの一般的なタスクを実行できます。独自のループを作成するのではなく、これらのルーチンを使用すると、パフォーマンスが頻繁に最適化されるため、コードの速度が向上します。

一般的なジョブの組み込み関数 (map()、filter()、sorted() など) を利用してカスタム ループを作成した場合のパフォーマンスを比較するサンプル コードを作成してみましょう。さまざまなマッピング、フィルタリング、並べ替え方法がどの程度うまく機能するかを評価します。

BuiltInFunctions.py:

輸入 タイメイ として って
#numbers_list のサンプルリスト
数値リスト = リスト ( 範囲 ( 1 10000 ) )

# ループを使用して数値リストを二乗する関数
確かに square_using_loop ( 数値リスト ) :
平方結果 = [
のために 1つで 数値リスト:
平方結果。 追加する ( 1 つ ** 2 )
戻る 平方結果
# 偶数のnumbers_listをループでフィルタリングする関数
確かに filter_even_using_loop ( 数値リスト ) :
フィルター結果 = [
のために 1つで 数値リスト:
もし 1%で 2 == 0 :
フィルター結果。 追加する ( 1つで )
戻る フィルター結果
# ループを使用してnumbers_listをソートする関数
確かに sort_using_loop ( 数値リスト ) :
戻る 並べ替えられた ( 数値リスト )
# map() を使用して数値リストを二乗する時間を測定します
マップ時間 = って。 タイメイ ( ラムダ : リスト ( 地図 ( ラムダ ×: × ** 2 数値リスト ) ) 番号 = 1000 )
# filter() を使用して偶数リストをフィルタリングする時間を測定します
フィルター時間 = って。 タイメイ ( ラムダ : リスト ( フィルター ( ラムダ x: x % 2 == 0 数値リスト ) ) 番号 = 1000 )
#sorted()を使用してnumbers_listをソートする時間を測定します
ソート時間 = って。 タイメイ ( ラムダ : 並べ替えられた ( 数値リスト ) 番号 = 1000 )
# ループを使用して数値リストを二乗する時間を測定する
ループマップ時間 = って。 タイメイ ( ラムダ : square_using_loop ( 数値リスト ) 番号 = 1000 )
# ループを使用して偶数リストをフィルタリングする時間を測定する
ループフィルター時間 = って。 タイメイ ( ラムダ : filter_even_using_loop ( 数値リスト ) 番号 = 1000 )
# ループを使用してnumbers_listをソートする時間を測定する
ループソート時間 = って。 タイメイ ( ラムダ : ソート使用ループ ( 数値リスト ) 番号 = 1000 )
印刷する ( 「数値リストには 10000 個の要素が含まれています」 )
印刷する ( f 「Map() 時間: {map_time:.6f} 秒」 )
印刷する ( f 「Filter() 時間: {filter_time:.6f} 秒」 )
印刷する ( f 「Sorted() 時間: {sorted_time:.6f} 秒」 )
印刷する ( f 「ループ(マップ)時間: {loop_map_time:.6f} 秒」 )
印刷する ( f 「ループ(フィルター)時間: {loop_filter_time:.6f} 秒」 )
印刷する ( f 「ループ (ソート) 時間: {loop_sorted_time:.6f} 秒」 )

これらの一般的なタスクでは、組み込み関数 (map()、filter()、sorted()) がカスタム ループよりも高速であることがわかります。 Python の組み込み関数は、これらのタスクを実行するためのより簡潔でわかりやすいアプローチを提供し、パフォーマンスが高度に最適化されています。

ループを最適化する

ループを記述する必要がある場合、ループを高速化するために実行できるテクニックがいくつかあります。一般に、range() ループは逆方向に反復するよりも高速です。これは、 range() がリストを反転せずに反復子を生成するためです。これは、長いリストに対してコストのかかる操作となる可能性があります。さらに、 range() はメモリ内に新しいリストを構築しないため、メモリの使用量が少なくなります。

最適化ループ.py:

輸入 タイメイ として って
#numbers_list のサンプルリスト
数値リスト = リスト ( 範囲 ( 1 100000 ) )
# リストを逆順に反復する関数
確かに ループリバース反復 ( ) :
結果_反転 = [
のために j 範囲 ( のみ ( 数値リスト ) - 1 - 1 - 1 ) :
結果_逆転。 追加する ( 数値リスト [ j )
戻る 結果_反転
# range() を使用してリストを反復する関数
確かに ループ範囲反復 ( ) :
結果の範囲 = [
のために k 範囲 ( のみ ( 数値リスト ) ) :
結果の範囲。 追加する ( 数値リスト [ k )
戻る 結果の範囲
# 逆反復の実行にかかる時間を測定する
reverse_time = って。 タイメイ ( ループリバース反復 番号 = 1000 )
# 範囲の反復の実行にかかる時間を測定する
範囲時間 = って。 タイメイ ( ループ範囲反復 番号 = 1000 )
印刷する ( 「番号リストには 100000 件のレコードが含まれています」 )
印刷する ( f 「逆反復時間: {reverse_time:.6f} 秒」 )
印刷する ( f 「範囲の反復時間: {range_time:.6f} 秒」 )

不必要な関数呼び出しを避ける

関数が呼び出されるたびに、ある程度のオーバーヘッドが発生します。不要な関数呼び出しが回避されると、コードはより高速に実行されます。たとえば、値を計算する関数を繰り返し実行するのではなく、計算結果を変数に格納して使用してみます。

プロファイリング用のツール

コードのパフォーマンスについて詳しく知るには、組み込みプロファイリングに加えて、cProfile、Pyflame、SnakeViz などの外部プロファイリング パッケージを利用できます。

結果をキャッシュする

コードで負荷の高い計算を実行する必要がある場合は、時間を節約するために結果をキャッシュすることを検討するかもしれません。

コードのリファクタリング

読みやすく保守しやすくするためにコードをリファクタリングすることが、コードの最適化に必要な場合があります。より高速なプログラムはよりクリーンになる可能性もあります。

ジャストインタイム コンパイル (JIT) を使用する

PyPy や Numba などのライブラリは、特定の種類の Python コードを大幅に高速化できる JIT コンパイルを提供できます。

Python をアップグレードする

新しいバージョンにはパフォーマンスが向上していることが多いため、Python の最新バージョンを使用していることを確認してください。

並列処理と同時実行性

並列化できるプロセスについては、マルチプロセッシング、スレッド化、非同期などの並列および同期技術を調査してください。

ベンチマークとプロファイリングが最適化の主な推進要因であることを忘れないでください。パフォーマンスに最も大きな影響を与えるコード領域の改善に集中し、改善を継続的にテストして、さらなる欠陥を引き起こすことなく望ましい効果が得られることを確認します。

結論

結論として、Python コードの最適化は、パフォーマンスとリソースの効率性を向上させるために非常に重要です。開発者は、適切なデータ構造の選択、組み込み関数の活用、余分なループの削減、メモリの効果的な管理などのさまざまなテクニックを使用して、Python アプリケーションの実行速度と応答性を大幅に向上させることができます。継続的なベンチマークとプロファイリングによって最適化の取り組みが方向付けられ、コードの進歩が現実世界のパフォーマンス要件に確実に一致するようにする必要があります。長期的なプロジェクトの成功を保証し、新たな問題が発生する可能性を低くするには、コードの可読性と保守性の目標と常にバランスをとりながらコードを最適化する必要があります。