ホームページ  >  記事  >  バックエンド開発  >  Pythonの実行効率を高めるテクニックとは?

Pythonの実行効率を高めるテクニックとは?

王林
王林転載
2023-05-11 14:13:061394ブラウズ

開始する前に、関数の実行時間をカウントする Python デコレータを開発できます。これは、さまざまな Python テクニックを使用した後、時間の統計に使用されます。

# 导入时间提取的time模块
from time import time

import dis


def compute_time(func_):
    '''
    计算函数的运行时间
    '''

    def func_time(*arg, **kw):
        t1 = time()
        result = func_(*arg, **kw)
        t2 = time()
        print(f"{func_.__name__: >10} : {t2 - t1:.6f} 秒")
        return result

    return func_time

上記の compute_time 時間計算関数を開発しましたが、それが正常に使用されるかどうかをテストするための hello_world 関数を開発できます。

@compute_time
def hello_world():
    print("hello_world!")


hello_world()

# hello_world!
# hello_world : 0.000000 秒

hello_world 関数のテストを通じて、時間デコレータ compute_time が関数の実行時間を正常に計算できることが証明されました。

次に、Python の実行速度を向上させ、実行時間の結果を提供する次の 5 つの方法を正式に紹介します。

1. 標準ライブラリまたは非標準ライブラリの合理的な使用

開発プロセス中に Python の標準ライブラリまたは非標準ライブラリを過小評価してはなりません。正直に言うと、同じビジネスコードを書くことがあります。確かに、大手のような完璧なものは存在しません。

たとえば、次のような業務では、Python のリストの値を文字列に変換する必要があるのですが、まず、次のコード ブロックがどのように記述されているかを見てください。

# 初始化一个list列表
list_ = ['a', 'b', 'c'] * 10000


@compute_time
def func_1(list_=None):
    '''
    列表元素转字符串函数
    '''
    str_ = ''
    for s in list_:
        str_ = str_ + s
    return str_


func_1(list_)


# func_1 : 0.001999 秒

私が作成した従来の方法を使用して上記の func_1 関数の実行を変換するのはより複雑で、0.001999 秒かかります。

@compute_time
def func_2(list_=None):
    '''
    列表元素转字符串
    '''
    return ''.join(list_)


func_2(list_)

# func_2 : 0.000000 秒

func_1 関数の実行時間と比較すると、func_2 の実行時間はほとんど無視できるほどであり、10 進数 6 桁ではまったく変化が見られません。

2. ループの使用を減らす

実際、通常の開発プロセスから、リスト導出、反復などを使用したシリアル化可能なデータ処理方法の方が for ループよりも便利であることがわかりました。 、 効率的。

以下では、例を使用して問題を説明することもできます。たとえば、リスト内の 2 で割り切れる数値を選択する必要があります。

# 初始化循环次数n
n = 100000


@compute_time
def func_3(n=None):
    list_ = []
    for m in range(n):
        if m % 2 == 0:
            list_.append(m)
    return list_


@compute_time
def func_4(n=None):
    return [m for m in range(n) if m % 2 == 0]


func_3(n)

func_4(n)

# func_3 : 0.004986 秒
# func_4 : 0.003014 秒

func_3 関数と func_4 関数を比較すると、まず、func_4 のメソッドは func_3 よりもはるかに簡単です。

そして、時間の点では、func_4 はリスト導出を使用して、通常の for ループよりも 1/4 高速に実行されます。

3. コードの繰り返し実行に注意する

コードの繰り返し実行については、通常の開発方法で誰もが経験することができます。つまり、公開コードとして 1 回だけ実行できます。ブロック。

パブリックに使用できるコード ブロックをループに追加できます。これは、コード ブロックの実行効率にのみ影響します。

たとえば、文字列内の特定の要素を検索するには、Python の re モジュールを使用する必要があります。時間の結果を比較する 2 つの方法を次に示します。

# 导入正则表达式匹配模块
import re


@compute_time
def func_5(str_=None):
    for s in str_:
        result = re.search(r'a*[a-z]?c', s)


@compute_time
def func_6(str_=None):
    repx = re.compile(r'a*[a-z]?c')
    for s in str_:
        result = repx.search(s)


func_5('abcdefg1234oks' * 1000)

func_6('abcdefg1234oks' * 1000)

# func_5 : 0.006999 秒
# func_6 : 0.002000 秒

func_5 と func_6 の業務実装方法を比較すると、re モジュールのコンパイル正規一致オブジェクトを for ループの外層に直接配置することで、実行時間が 3 倍以上短縮されました。 。

これは、検索を使用してループ内で通常のオブジェクトに直接一致させると、ループ内に通常の一致するオブジェクトが継続的に作成され、
for ループの処理負荷が増大し、速度が低下するためです。

4. グローバル変数の使用を減らす

この点を説明するとき、グローバル変数は常に存在し、プログラムの実行中に消えることはないことを理解する必要があります。

グローバル変数が多すぎると、操作中に多くのメモリが占​​有されます。グローバル変数と比較してローカル変数を使用した方が効率的です。

以下では、グローバル変数とローカル変数の実行時間を比較する 2 つの方法の例を使用します。

mes_1 = 'ss1'

mes_2 = 'ss2'

mes_3 = 'ss3'


@compute_time
def func_7():
    result = mes_1 + mes_2 + mes_3
    return result


@compute_time
def func_8():
    me_1 = 'ss1'
    me_2 = 'ss2'
    me_3 = 'ss3'
    result = me_1 + me_2 + me_3
    return result


func_7()

func_8()


# func_7 : 0.000997 秒
# func_8 : 0.000000 秒

問題を説明するために、上で通常の加算計算を実行しましたが、func_8 関数がローカル変数を使用する方法は確かに高速です。

5. 合理的なデータ構造を使用する

ほとんどの Python 開発プロセスでは、多くの人が便宜上データを処理するためにリストを使用する必要があります。

Python にはリスト、タプル、セット、辞書という 4 つのデータ構造が組み込まれており、適切なビジネス シナリオで適切なデータ構造を使用してデータを処理することにより、計算の実行効率も向上します。

例: 以下ではリスト list とタプル tuple から対応するインデックス位置の値を抽出します。

@compute_time
def func_9():
    data = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
    print(data[3])


@compute_time
def func_10():
    data = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h')
    print(data[3])

func_9()

func_10()

# func_9 : 0.000000 秒
# func_10 : 0.000000 秒

func_9 関数と func_10 関数を実行すると、両者の時間の差は大きくなく、少なくとも小数点以下 6 桁以内では結果を区別できないことがわかりました。

print('func_9汇编产生的机器码:')
dis.dis(func_9)

print('func_10汇编产生的机器码:')
dis.dis(func_10)

最後に、func_9 と func_10 のアセンブリ機械コードをそれぞれ確認したところ、明らかにリスト リスト処理の方がより多くの機械コードを生成していることがわかりました。

rree

以上がPythonの実行効率を高めるテクニックとは?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。