Heim  >  Artikel  >  Backend-Entwicklung  >  Welche Techniken gibt es, um die Ausführungseffizienz von Python zu verbessern?

Welche Techniken gibt es, um die Ausführungseffizienz von Python zu verbessern?

王林
王林nach vorne
2023-05-11 14:13:061394Durchsuche

Bevor Sie beginnen, können Sie einen Python-Dekorator entwickeln, der die Laufzeit von Funktionen zählt, der später für Zeitstatistiken verwendet wird, nachdem wir verschiedene Python-Techniken verwendet haben.

# 导入时间提取的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

Wir haben die obige Zeitberechnungsfunktion „compute_time“ entwickelt. Wir können eine Funktion „hello_world“ entwickeln, um zu testen, ob sie normal verwendet wird.

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


hello_world()

# hello_world!
# hello_world : 0.000000 秒

Durch den Test der Funktion „hello_world“ wurde bewiesen, dass unser Zeitdekorator „compute_time“ normalerweise die Laufzeit der Funktion berechnen kann.

Als nächstes beginnen wir offiziell mit der offiziellen Einführung der folgenden fünf Möglichkeiten, um die Laufgeschwindigkeit von Python zu verbessern und Zeitlaufergebnisse zu liefern.

1. Angemessene Verwendung von Standard- oder Nicht-Standard-Bibliotheken

Um ehrlich zu sein, schreiben wir manchmal Das Gleiche Der Geschäftscodeblock ist in der Tat nicht so perfekt wie der der Großen.

Im folgenden Geschäft müssen wir beispielsweise die Werte in einer Python-Liste in Zeichenfolgen konvertieren. Schauen Sie sich zunächst an, wie der folgende Codeblock geschrieben ist.

# 初始化一个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 秒

Die Verwendung der von mir selbst geschriebenen traditionellen Methode zum Konvertieren der Schritte durch die Ausführung der Funktion func_1 oben ist komplizierter und dauert 0,001999 Sekunden.

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


func_2(list_)

# func_2 : 0.000000 秒

Verglichen mit der Laufzeit der Funktion func_1 ist die Laufzeit von func_2 fast vernachlässigbar und die sechsstellige Dezimalzahl kann die Änderung überhaupt nicht erkennen.

2. Reduzieren Sie die Verwendung von Schleifen

Aus dem normalen Entwicklungsprozess wurde herausgefunden, dass serialisierbare Datenverarbeitungsmethoden mithilfe von Listenableitung, Iteration usw. besser sind als für The Zyklus ist bequemer und effizienter.

Unten können wir auch ein Beispiel verwenden, um das Problem zu veranschaulichen. Beispielsweise müssen wir eine Zahl in einer Liste auswählen, die durch 2 geteilt werden kann.

# 初始化循环次数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 秒

Durch den Vergleich der Funktion func_3 und der Funktion func_4 ist zunächst einmal festzustellen, dass die Methode von func_4 viel einfacher ist als die von func_3.

Und in Bezug auf die Zeit verwendet func_4 die Listenableitung, um 1/4 schneller als die gewöhnliche for-Schleife auszuführen.

3. Achten Sie auf die wiederholte Ausführung von Code

Was die wiederholte Ausführung von Code betrifft, können wir alle dies in unseren üblichen Entwicklungsmethoden erleben, das heißt, er kann einmal ausgeführt werden als öffentlicher Codeblock Das ist es.

Sie können der Schleife öffentlich verwendbare Codeblöcke hinzufügen, was sich nur auf die Ausführungseffizienz der Codeblöcke auswirkt.

Zum Beispiel müssen wir das Re-Modul von Python verwenden, um nach bestimmten Elementen in der Zeichenfolge zu suchen. Hier sind zwei Möglichkeiten, die Zeitergebnisse zu vergleichen.

# 导入正则表达式匹配模块
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 秒

Beim Vergleich der Geschäftsimplementierungsmethoden von func_5 und func_6 haben wir das reguläre Kompilierungsobjekt des Re-Moduls direkt in die äußere Schicht der for-Schleife eingefügt, und die Laufzeit wurde direkt um mehr als reduziert dreimal.

Dies liegt daran, dass die Verwendung der Suche zum Abgleichen regulärer Objekte direkt in der Schleife kontinuierlich reguläre übereinstimmende Objekte in der Schleife erstellt, was
den Verarbeitungsaufwand der for-Schleife erhöht und zu einer Verlangsamung der Geschwindigkeit führt runter.

4. Reduzieren Sie die Verwendung globaler Variablen

Bei der Erklärung müssen wir verstehen, dass globale Variablen immer existieren und während der Ausführung des Programms nicht verschwinden.

Zu viele globale Variablen führen dazu, dass während des Betriebs zu viel Speicher belegt wird. Die Verwendung lokaler Variablen ist effizienter als globale Variablen.

Im Folgenden verwenden wir Beispiele für zwei Methoden, um die Laufzeit globaler Variablen und lokaler Variablen zu vergleichen.

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 秒

Wir haben oben eine gewöhnliche Additionsberechnung durchgeführt, um das Problem zu veranschaulichen. Die Art und Weise, wie die Funktion func_8 lokale Variablen verwendet, ist tatsächlich schneller.

5. Verwenden Sie sinnvolle Datenstrukturen

In den meisten Python-Entwicklungsprozessen müssen viele Menschen aus Bequemlichkeitsgründen häufiger Listen verwenden.

Python verfügt über vier integrierte Datenstrukturen: Listen, Tupel, Mengen und Wörterbücher. Die Verwendung geeigneter Datenstrukturen zur Datenverarbeitung in geeigneten Geschäftsszenarien kann auch die Effizienz der Berechnungsausführung verbessern.

Zum Beispiel: Nachfolgend extrahieren wir den Wert an der entsprechenden Indexposition aus einer Liste und einem Tupel-Tupel.

@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 秒

Durch die Ausführung der Funktionen func_9 und func_10 haben wir festgestellt, dass der Zeitunterschied zwischen den beiden nicht groß ist, zumindest kann das Ergebnis nicht innerhalb von sechs Dezimalstellen unterschieden werden.

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

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

Abschließend haben wir uns die Assembler-Maschinencodes von func_9 bzw. func_10 angesehen und festgestellt, dass die Listenverarbeitung offensichtlich mehr Maschinencodes generiert.

# func_9汇编产生的机器码:
#  30           0 LOAD_GLOBAL              0 (time)
#               2 CALL_FUNCTION            0
#               4 STORE_FAST               2 (t1)
#
#  31           6 LOAD_DEREF               0 (func_)
#               8 LOAD_FAST                0 (arg)
#              10 LOAD_FAST                1 (kw)
#              12 CALL_FUNCTION_EX         1
#              14 STORE_FAST               3 (result)
#
#  32          16 LOAD_GLOBAL              0 (time)
#              18 CALL_FUNCTION            0
#              20 STORE_FAST               4 (t2)
#
#  33          22 LOAD_GLOBAL              1 (print)
#              24 LOAD_DEREF               0 (func_)
#              26 LOAD_ATTR                2 (__name__)
#              28 LOAD_CONST               1 (' >10')
#              30 FORMAT_VALUE             4 (with format)
#              32 LOAD_CONST               2 (' : ')
#              34 LOAD_FAST                4 (t2)
#              36 LOAD_FAST                2 (t1)
#              38 BINARY_SUBTRACT
#              40 LOAD_CONST               3 ('.6f')
#              42 FORMAT_VALUE             4 (with format)
#              44 LOAD_CONST               4 (' 秒')
#              46 BUILD_STRING             4
#              48 CALL_FUNCTION            1
#              50 POP_TOP
#
#  34          52 LOAD_FAST                3 (result)
#              54 RETURN_VALUE
# func_10汇编产生的机器码:
#  30           0 LOAD_GLOBAL              0 (time)
#               2 CALL_FUNCTION            0
#               4 STORE_FAST               2 (t1)
#
#  31           6 LOAD_DEREF               0 (func_)
#               8 LOAD_FAST                0 (arg)
#              10 LOAD_FAST                1 (kw)
#              12 CALL_FUNCTION_EX         1
#              14 STORE_FAST               3 (result)

Das obige ist der detaillierte Inhalt vonWelche Techniken gibt es, um die Ausführungseffizienz von Python zu verbessern?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen