Ako optimalizovať svoje skripty Python pre lepší výkon

Ako Optimalizovat Svoje Skripty Python Pre Lepsi Vykon



Optimalizácia skriptov Python pre lepší výkon zahŕňa identifikáciu a riešenie úzkych miest v našom kóde, vďaka čomu bude bežať rýchlejšie a efektívnejšie. Python je populárny a výkonný programovací jazyk, ktorý sa v súčasnosti používa v mnohých aplikáciách vrátane analýzy údajov, projektov ML (strojové učenie), vývoja webu a mnohých ďalších. Optimalizácia kódu Python je stratégia na zlepšenie rýchlosti a efektivity vývojárskeho programu pri vykonávaní akejkoľvek činnosti s použitím menšieho počtu riadkov kódu, menšej pamäte alebo dodatočných zdrojov. Veľký a neefektívny kód môže spomaliť program, čo môže mať za následok slabú spokojnosť klienta a možnú finančnú stratu alebo potrebu ďalšej práce na oprave a odstraňovaní problémov.

Je to potrebné pri vykonávaní úlohy, ktorá si vyžaduje spracovanie niekoľkých akcií alebo údajov. Preto vypnutie a vylepšenie niektorých neefektívnych blokov kódu a funkcií môže mať úžasné výsledky, ako napríklad:

  1. Zvýšte výkon aplikácie
  2. Vytvorte čitateľný a organizovaný kód
  3. Uľahčite monitorovanie a ladenie chýb
  4. Ušetrite značný výpočtový výkon a tak ďalej

Profilujte svoj kód

Skôr než začneme s optimalizáciou, je nevyhnutné identifikovať časti kódu projektu, ktoré ho spomaľujú. Techniky profilovania v Pythone zahŕňajú balíky cProfile a profile. Použite takéto nástroje na meranie rýchlosti vykonávania určitých funkcií a riadkov kódu. Modul cProfile vytvára správu, ktorá podrobne uvádza, ako dlho trvá spustenie každej funkcie skriptu. Tento prehľad nám môže pomôcť nájsť všetky funkcie, ktoré bežia pomaly, aby sme ich mohli vylepšiť.







Úryvok kódu:



importovať cProfile ako cP
def vypočítaťSúčet ( inputNumber ) :
súčet_vstupných_čísiel = 0
zatiaľ čo inputNumber > 0 :
súčet_vstupných_čísel + = inputNumber % 10
inputNumber // = 10
vytlačiť ( 'Súčet všetkých číslic v čísle vstupu je: 'súčet_čísel_vstupu'' )
vrátiť súčet_vstupných_čísiel
def main_func ( ) :
cP. behať ( 'calculateSum(9876543789)' )
ak __názov__ == '__Hlavná__' :
main_func ( )

Program vykoná celkovo päť volaní funkcií, ako je vidieť v prvom riadku výstupu. Podrobnosti o každom volaní funkcie sú zobrazené v nasledujúcich niekoľkých riadkoch vrátane počtu, koľkokrát bola funkcia vyvolaná, celkového trvania času vo funkcii, trvania času na volanie a celkového času vo funkcii (vrátane všetky funkcie, ktoré sa nazývajú).



Okrem toho program vytlačí správu na obrazovke s výzvou, ktorá ukazuje, že program dokončí čas vykonania všetkých svojich úloh do 0,000 sekúnd. To ukazuje, aký rýchly je program.





Vyberte správnu dátovú štruktúru

Výkonnostné charakteristiky závisia od štruktúry údajov. Najmä slovníky sú rýchlejšie na vyhľadávanie ako zoznamy týkajúce sa univerzálneho úložiska. Vyberte štruktúru údajov, ktorá je najvhodnejšia pre operácie, ktoré vykonáme s vašimi údajmi, ak ich poznáte. Nasledujúci príklad skúma účinnosť rôznych dátových štruktúr pre identický proces s cieľom určiť, či je prítomný prvok v dátovej štruktúre.



Hodnotíme čas potrebný na kontrolu, či je prvok prítomný v každej dátovej štruktúre – v zozname, množine a slovníku – a porovnávame ich.

OptimizeDataType.py:

importovať Timei ako tt
importovať náhodný ako rndobj
# Vytvorte zoznam celých čísel
zoznam náhodných_údajov = [ rndobj. randint ( 1 , 10 000 ) pre _ v rozsah ( 10 000 ) ]
# Vytvorte sadu z rovnakých údajov
random_data_set = nastaviť ( zoznam náhodných_údajov )

# Vytvorte slovník s rovnakými údajmi ako kľúče
obj_DataDictionary = { na jeden: žiadne pre na jeden v zoznam náhodných_údajov }

# Prvok na vyhľadanie (existuje v údajoch)
náhodné_číslo_na_nájdenie = rndobj. výber ( zoznam náhodných_údajov )

# Zmerajte čas na kontrolu členstva v zozname
zoznam_čas = tt. Timei ( lambda : náhodné_číslo_na_nájdenie v zoznam náhodných_údajov , číslo = 1000 )

# Zmerajte čas na kontrolu členstva v súprave
nastav čas = tt. Timei ( lambda : náhodné_číslo_na_nájdenie v random_data_set , číslo = 1000 )

# Zmerajte čas na kontrolu členstva v slovníku
dict_time = tt. Timei ( lambda : náhodné_číslo_na_nájdenie v obj_DataDictionary , číslo = 1000 )

vytlačiť ( f 'Čas kontroly členstva v zozname: {list_time:.6f} sekúnd' )
vytlačiť ( f 'Nastaviť čas kontroly členstva: {set_time:.6f} sekúnd' )
vytlačiť ( f 'Čas kontroly členstva v slovníku: {dict_time:.6f} sekúnd' )

Tento kód porovnáva výkonnosť zoznamov, sád a slovníkov pri vykonávaní kontrol členstva. Vo všeobecnosti sú množiny a slovníky podstatne rýchlejšie ako zoznamy na testy členstva, pretože používajú vyhľadávania založené na hash, takže majú priemernú časovú zložitosť O(1). Na druhej strane zoznamy musia vykonávať lineárne vyhľadávanie, čo vedie k testom členstva s časovou zložitosťou O(n).

  Automaticky vygenerovaná snímka obrazovky počítača Popis

Namiesto slučiek použite vstavané funkcie

Množstvo vstavaných funkcií alebo metód v Pythone možno použiť na vykonávanie typických úloh, ako je filtrovanie, triedenie a mapovanie. Používanie týchto rutín namiesto vytvárania vlastných slučiek pomáha urýchliť kód, pretože sú často optimalizované na výkon.

Vytvorme nejaký vzorový kód na porovnanie výkonu vytvárania vlastných slučiek s využitím vstavaných funkcií pre typické úlohy (ako je map(), filter() a sort()). Vyhodnotíme, ako dobre fungujú rôzne metódy mapovania, filtrácie a triedenia.

BuiltInFunctions.py:

importovať Timei ako tt
# Vzorový zoznam čísel_zoznam
číselný_zoznam = zoznam ( rozsah ( 1 , 10 000 ) )

# Funkcia na štvorcový zoznam čísel pomocou slučky
def square_using_loop ( číselný_zoznam ) :
štvorcový_výsledok = [ ]
pre na jeden v zoznam_čísel:
štvorcový_výsledok. priložiť ( na jeden ** 2 )
vrátiť štvorcový_výsledok
# Funkcia na filtrovanie zoznamu párnych čísel pomocou slučky
def filter_even_using_loop ( číselný_zoznam ) :
filter_result = [ ]
pre na jeden v zoznam_čísel:
ak na jeden % 2 == 0 :
filter_result. priložiť ( na jeden )
vrátiť filter_result
# Funkcia na triedenie zoznamu čísel pomocou slučky
def sort_using_loop ( číselný_zoznam ) :
vrátiť triedené ( číselný_zoznam )
# Zmerajte čas do štvorcového zoznamu čísel pomocou mapy ()
map_time = tt. Timei ( lambda : zoznam ( mapa ( lambda x: x ** 2 , číselný_zoznam ) ) , číslo = 1000 )
# Zmerajte čas na filtrovanie zoznamu párnych čísel pomocou filtra ()
filter_time = tt. Timei ( lambda : zoznam ( filter ( lambda x: x % 2 == 0 , číselný_zoznam ) ) , číslo = 1000 )
# Zmerajte čas na zoradenie zoznamu čísel pomocou zoradeného ()
zoradený_čas = tt. Timei ( lambda : triedené ( číselný_zoznam ) , číslo = 1000 )
# Zmerajte čas do štvorcového zoznamu čísel pomocou slučky
loop_map_time = tt. Timei ( lambda : square_using_loop ( číselný_zoznam ) , číslo = 1000 )
# Zmerajte čas na filtrovanie zoznamu párnych čísel pomocou slučky
loop_filter_time = tt. Timei ( lambda : filter_even_using_loop ( číselný_zoznam ) , číslo = 1000 )
# Zmerajte čas na zoradenie zoznamu čísel pomocou slučky
loop_sorted_time = tt. Timei ( lambda : sort_using_loop ( číselný_zoznam ) , číslo = 1000 )
vytlačiť ( 'Zoznam čísel obsahuje 10 000 prvkov' )
vytlačiť ( f 'Map() Time: {map_time:.6f} sekúnd' )
vytlačiť ( f 'Filter() Time: {filter_time:.6f} sekúnd' )
vytlačiť ( f 'Sorted() Time: {sorted_time:.6f} sekúnd' )
vytlačiť ( f 'Čas slučky (mapy): {loop_map_time:.6f} sekúnd' )
vytlačiť ( f 'Čas cyklu (filtra): {loop_filter_time:.6f} sekúnd' )
vytlačiť ( f 'Čas cyklu (triedeného): {loop_sorted_time:.6f} sekúnd' )

Pravdepodobne si všimneme, že vstavané funkcie (map(), filter() a sort()) sú rýchlejšie ako vlastné slučky pre tieto bežné úlohy. Vstavané funkcie v Pythone ponúkajú stručnejší a zrozumiteľnejší prístup k vykonávaniu týchto úloh a sú vysoko optimalizované pre výkon.

Optimalizujte slučky

Ak je písanie slučiek nevyhnutné, existuje niekoľko techník, ktoré môžeme urobiť na ich urýchlenie. Vo všeobecnosti je cyklus range() rýchlejší ako iterácia dozadu. Je to preto, že range() generuje iterátor bez invertovania zoznamu, čo môže byť pri dlhých zoznamoch nákladná operácia. Navyše, keďže range() nevytvára nový zoznam v pamäti, využíva menej pamäte.

OptimizeLoop.py:

importovať Timei ako tt
# Vzorový zoznam čísel_zoznam
číselný_zoznam = zoznam ( rozsah ( 1 , 100 000 ) )
# Funkcia na iteráciu zoznamu v opačnom poradí
def loop_reverse_iteration ( ) :
result_reverse = [ ]
pre j v rozsah ( len ( číselný_zoznam ) - 1 , - 1 , - 1 ) :
result_reverse. priložiť ( číselný_zoznam [ j ] )
vrátiť result_reverse
# Funkcia na iteráciu zoznamu pomocou range()
def loop_range_iteration ( ) :
rozsah_výsledkov = [ ]
pre k v rozsah ( len ( číselný_zoznam ) ) :
rozsah_výsledkov. priložiť ( číselný_zoznam [ k ] )
vrátiť rozsah_výsledkov
# Zmerajte čas potrebný na vykonanie spätnej iterácie
reverzný_čas = tt. Timei ( loop_reverse_iteration , číslo = 1000 )
# Zmerajte čas potrebný na vykonanie iterácie rozsahu
rozsah_čas = tt. Timei ( loop_range_iteration , číslo = 1000 )
vytlačiť ( 'Zoznam čísel obsahuje 100 000 záznamov' )
vytlačiť ( f 'Čas spätnej iterácie: {reverse_time:.6f} sekúnd' )
vytlačiť ( f 'Čas iterácie rozsahu: {range_time:.6f} sekúnd' )

Vyhnite sa zbytočným volaniam funkcií

Pri každom volaní funkcie existuje určitá réžia. Kód beží rýchlejšie, ak sa vyhnete zbytočným volaniam funkcií. Napríklad namiesto opakovaného vykonávania funkcie, ktorá vypočítava hodnotu, skúste výsledok výpočtu uložiť do premennej a použiť ju.

Nástroje na profilovanie

Ak sa chcete dozvedieť viac o výkone vášho kódu, okrem vstavaného profilovania môžeme využiť externé profilovacie balíky ako cProfile, Pyflame alebo SnakeViz.

Výsledky vyrovnávacej pamäte

Ak náš kód potrebuje vykonávať drahé výpočty, môžeme zvážiť uloženie výsledkov do vyrovnávacej pamäte, aby sme ušetrili čas.

Refaktorovanie kódu

Refaktorovanie kódu, aby sa dal ľahšie čítať a udržiavať, je niekedy nevyhnutnou súčasťou jeho optimalizácie. Rýchlejší program môže byť aj čistejší.

Použite kompiláciu Just-in-Time (JIT)

Knižnice ako PyPy alebo Numba môžu poskytnúť kompiláciu JIT, ktorá môže výrazne urýchliť určité typy kódu Python.

Inovujte Python

Uistite sa, že používate najnovšiu verziu Pythonu, pretože novšie verzie často obsahujú vylepšenia výkonu.

Paralelnosť a súbežnosť

Pre procesy, ktoré možno paralelizovať, preskúmajte paralelné a synchronizačné techniky, ako je multiprocessing, threading alebo asyncio.

Pamätajte, že benchmarking a profilovanie by mali byť hlavnými hnacími motormi optimalizácie. Sústreďte sa na zlepšovanie oblastí nášho kódu, ktoré majú najvýznamnejší vplyv na výkon, a neustále testujte svoje vylepšenia, aby ste sa uistili, že majú požadované účinky bez toho, aby vnášali ďalšie chyby.

Záver

Na záver, optimalizácia kódu Python je rozhodujúca pre lepší výkon a efektívnosť zdrojov. Vývojári môžu výrazne zvýšiť rýchlosť vykonávania a odozvu svojich aplikácií Python pomocou rôznych techník, ako je výber vhodných dátových štruktúr, využitie vstavaných funkcií, zníženie nadbytočných slučiek a efektívna správa pamäte. Nepretržité porovnávanie a profilovanie by malo nasmerovať úsilie na optimalizáciu a zabezpečiť, aby vylepšenia kódu zodpovedali požiadavkám na výkon v reálnom svete. Aby sa zaručil dlhodobý úspech projektu a znížila sa možnosť zavedenia nových problémov, optimalizácia kódu by mala byť neustále v rovnováhe s cieľmi čitateľnosti a udržiavateľnosti kódu.