Cara Mengoptimumkan Skrip Python Anda untuk Prestasi Lebih Baik

Cara Mengoptimumkan Skrip Python Anda Untuk Prestasi Lebih Baik



Mengoptimumkan skrip Python untuk prestasi yang lebih baik melibatkan mengenal pasti dan menangani kesesakan dalam kod kami, menjadikannya berjalan lebih pantas dan lebih cekap. Python ialah bahasa pengaturcaraan yang popular dan berkuasa yang digunakan dalam pelbagai aplikasi pada masa kini termasuk analisis data, projek ML (pembelajaran mesin), pembangunan web dan banyak lagi. Pengoptimuman kod Python ialah strategi untuk meningkatkan kelajuan dan kecekapan program pembangun apabila melakukan sebarang aktiviti menggunakan lebih sedikit baris kod, kurang memori atau sumber tambahan. Kod yang besar dan tidak cekap boleh memperlahankan program yang boleh mengakibatkan kepuasan pelanggan yang lemah dan potensi kerugian kewangan, atau keperluan untuk lebih banyak kerja untuk diperbaiki dan diselesaikan.

Ia adalah perlu semasa melakukan tugas yang memerlukan pemprosesan beberapa tindakan atau data. Oleh itu, menukar dan meningkatkan beberapa blok dan fungsi kod yang tidak berkesan boleh menghasilkan hasil yang menakjubkan seperti berikut:

  1. Tingkatkan prestasi aplikasi
  2. Buat kod yang boleh dibaca dan teratur
  3. Jadikan pemantauan ralat dan penyahpepijatan lebih mudah
  4. Menjimatkan kuasa pengiraan yang banyak dan sebagainya

Profil Kod Anda

Sebelum kita mula mengoptimumkan, adalah penting untuk mengenal pasti bahagian kod projek yang memperlahankannya. Teknik untuk membuat profil dalam Python termasuk cProfile dan pakej profil. Gunakan alat sedemikian untuk mengukur seberapa cepat fungsi dan baris kod tertentu dilaksanakan. Modul cProfile menghasilkan laporan yang memperincikan tempoh masa setiap fungsi skrip dijalankan. Laporan ini boleh membantu kami mencari mana-mana fungsi yang berjalan perlahan supaya kami boleh memperbaikinya.







Coretan Kod:



import cProfil sebagai cP
def hitungJumlah ( inputNombor ) :
jumlah_nombor_masukan = 0
sementara inputNombor > 0 :
jumlah_nombor_masukan + = inputNumber % 10
inputNumber // = 10
cetak ( 'Jumlah Semua Digit dalam Nombor Input ialah: 'jumlah_nombor_input'' )
kembali jumlah_nombor_masukan
def main_func ( ) :
cP. lari ( 'calculateSum(9876543789)' )
jika __nama__ == '__utama__' :
main_func ( )

Program ini membuat sejumlah lima panggilan fungsi seperti yang dilihat pada baris pertama output. Butiran setiap panggilan fungsi ditunjukkan dalam beberapa baris berikut termasuk bilangan kali fungsi itu digunakan, tempoh keseluruhan masa dalam fungsi, tempoh masa setiap panggilan dan jumlah keseluruhan masa dalam fungsi (termasuk semua fungsi yang dipanggil).



Selain itu, program mencetak laporan pada skrin gesaan yang menunjukkan bahawa program melengkapkan masa pelaksanaan semua tugasnya dalam masa 0.000 saat. Ini menunjukkan betapa cepatnya program ini.





Pilih Struktur Data yang Betul

Ciri prestasi bergantung kepada struktur data. Khususnya, kamus lebih cepat untuk carian daripada senarai mengenai storan tujuan umum. Pilih struktur data yang paling sesuai untuk operasi yang akan kami jalankan pada data anda jika anda mengetahuinya. Contoh berikut menyiasat keberkesanan struktur data yang berbeza untuk proses yang sama untuk menentukan sama ada unsur dalam struktur data wujud.



Kami menilai masa yang diperlukan untuk menyemak sama ada unsur hadir dalam setiap struktur data—senarai, set dan kamus—dan membandingkannya.

OptimizeDataType.py:

import Timei sebagai tt
import rawak sebagai rndobj
# Hasilkan senarai integer
senarai_data_rambang = [ rndobj. randit ( 1 , 10000 ) untuk _ dalam julat ( 10000 ) ]
# Buat set daripada data yang sama
set_data_rawak = ditetapkan ( senarai_data_rambang )

# Buat kamus dengan data yang sama seperti kunci
obj_DataDictionary = { pada satu: tiada untuk pada satu dalam senarai_data_rambang }

# Elemen untuk dicari (wujud dalam data)
nombor_rambang_untuk_cari = rndobj. pilihan ( senarai_data_rambang )

# Ukur masa untuk menyemak keahlian dalam senarai
senarai_masa = tt. Timei ( lambda : nombor_rambang_untuk_cari dalam senarai_data_rambang , nombor = 1000 )

# Ukur masa untuk menyemak keahlian dalam satu set
tetapkan masa = tt. Timei ( lambda : nombor_rambang_untuk_cari dalam set_data_rawak , nombor = 1000 )

# Ukur masa untuk menyemak keahlian dalam kamus
dict_time = tt. Timei ( lambda : nombor_rambang_untuk_cari dalam obj_DataDictionary , nombor = 1000 )

cetak ( f 'Masa semak keahlian senarai: {list_time:.6f} saat' )
cetak ( f 'Tetapkan masa semakan keahlian: {set_time:.6f} saat' )
cetak ( f 'Masa semak keahlian kamus: {dict_time:.6f} saat' )

Kod ini membandingkan prestasi senarai, set dan kamus semasa melakukan semakan keahlian. Secara umum, set dan kamus adalah jauh lebih pantas daripada senarai untuk ujian keahlian kerana mereka menggunakan carian berasaskan cincang, jadi mereka mempunyai purata kerumitan masa O(1). Senarai, sebaliknya, mesti melakukan carian linear yang menghasilkan ujian keahlian dengan kerumitan masa O(n).

  Tangkapan skrin komputer Perihalan dijana secara automatik

Gunakan Fungsi Terbina Dalam Daripada Gelung

Banyak fungsi atau kaedah terbina dalam dalam Python boleh digunakan untuk menjalankan tugas biasa seperti penapisan, pengisihan dan pemetaan. Menggunakan rutin ini dan bukannya membuat gelung seseorang membantu mempercepatkan kod kerana ia kerap dioptimumkan prestasi.

Mari bina beberapa kod sampel untuk membandingkan prestasi mencipta gelung tersuai dengan menggunakan fungsi terbina dalam untuk kerja biasa (seperti map(), filter(), dan sorted()). Kami akan menilai prestasi pelbagai kaedah pemetaan, penapisan dan pengisihan.

BuiltInFunctions.py:

import Timei sebagai tt
# Contoh senarai nombor_senarai
senarai_nombor = senarai ( julat ( 1 , 10000 ) )

# Berfungsi untuk petak nombor_senarai menggunakan gelung
def persegi_menggunakan_gelung ( senarai_nombor ) :
hasil_persegi = [ ]
untuk pada satu dalam senarai_nombor:
hasil_persegi. tambahkan ( pada satu ** 2 )
kembali hasil_persegi
# Berfungsi untuk menapis nombor_senarai genap menggunakan gelung
def filter_even_using_loop ( senarai_nombor ) :
penapis_hasil = [ ]
untuk pada satu dalam senarai_nombor:
jika pada satu % 2 == 0 :
penapis_hasil. tambahkan ( pada satu )
kembali penapis_hasil
# Berfungsi untuk mengisih numbers_list menggunakan gelung
def sort_using_loop ( senarai_nombor ) :
kembali disusun ( senarai_nombor )
# Ukur masa untuk petak nombor_senarai menggunakan map()
masa_peta = tt. Timei ( lambda : senarai ( peta ( lambda x: x ** 2 , senarai_nombor ) ) , nombor = 1000 )
# Ukur masa untuk menapis nombor_senarai genap menggunakan penapis()
masa_penapis = tt. Timei ( lambda : senarai ( penapis ( lambda x: x % 2 == 0 , senarai_nombor ) ) , nombor = 1000 )
# Ukur masa untuk mengisih numbers_list menggunakan sorted()
masa_isih = tt. Timei ( lambda : disusun ( senarai_nombor ) , nombor = 1000 )
# Ukur masa untuk petak nombor_senarai menggunakan gelung
loop_map_time = tt. Timei ( lambda : square_using_loop ( senarai_nombor ) , nombor = 1000 )
# Ukur masa untuk menapis nombor_senarai genap menggunakan gelung
loop_filter_time = tt. Timei ( lambda : filter_even_using_loop ( senarai_nombor ) , nombor = 1000 )
# Ukur masa untuk mengisih nombor_senarai menggunakan gelung
loop_sorted_time = tt. Timei ( lambda : sort_using_loop ( senarai_nombor ) , nombor = 1000 )
cetak ( 'Senarai Nombor mengandungi 10000 elemen' )
cetak ( f 'Map() Time: {map_time:.6f} seconds' )
cetak ( f 'Filter() Time: {filter_time:.6f} seconds' )
cetak ( f 'Masa Diisih(): {masa_isih:.6f} saat' )
cetak ( f 'Masa (Peta) Gelung: {loop_map_time:.6f} saat' )
cetak ( f 'Masa Gelung (Penapis): {loop_filter_time:.6f} saat' )
cetak ( f 'Masa Gelung (Diisih): {loop_sorted_time:.6f} saat' )

Kami mungkin akan melihat bahawa fungsi terbina dalam (map(), filter(), dan sorted()) adalah lebih pantas daripada gelung tersuai untuk tugasan biasa ini. Fungsi terbina dalam Python menawarkan pendekatan yang lebih ringkas dan mudah difahami untuk menjalankan tugas ini dan sangat dioptimumkan untuk prestasi.

Optimumkan Gelung

Jika menulis gelung adalah perlu, terdapat beberapa teknik yang boleh kita lakukan untuk mempercepatkannya. Secara amnya, gelung julat() adalah lebih cepat daripada lelaran ke belakang. Ini kerana range() menjana iterator tanpa menyongsangkan senarai yang boleh menjadi operasi yang mahal untuk senarai yang panjang. Selain itu, memandangkan range() tidak membina senarai baharu dalam memori, ia menggunakan kurang memori.

OptimizeLoop.py:

import Timei sebagai tt
# Contoh senarai nombor_senarai
senarai_nombor = senarai ( julat ( 1 , 100000 ) )
# Berfungsi untuk mengulang senarai dalam susunan terbalik
def loop_reverse_iteration ( ) :
result_reverse = [ ]
untuk j dalam julat ( sahaja ( senarai_nombor ) - 1 , - 1 , - 1 ) :
result_reverse. tambahkan ( senarai_nombor [ j ] )
kembali result_reverse
# Berfungsi untuk mengulang senarai menggunakan julat()
def loop_range_iteration ( ) :
julat_hasil = [ ]
untuk k dalam julat ( sahaja ( senarai_nombor ) ) :
julat_hasil. tambahkan ( senarai_nombor [ k ] )
kembali julat_hasil
# Ukur masa yang diperlukan untuk melakukan lelaran terbalik
masa_terbalik = tt. Timei ( loop_reverse_iteration , nombor = 1000 )
# Ukur masa yang diperlukan untuk melakukan lelaran julat
julat_masa = tt. Timei ( loop_range_iteration , nombor = 1000 )
cetak ( 'Senarai nombor mengandungi 100000 rekod' )
cetak ( f 'Masa Lelaran Terbalik: {reverse_time:.6f} saat' )
cetak ( f 'Masa Lelaran Julat: {range_time:.6f} saat' )

Elakkan Panggilan Fungsi yang Tidak Diperlukan

Terdapat beberapa overhed setiap kali fungsi dipanggil. Kod berjalan lebih cepat jika panggilan fungsi yang tidak perlu dielakkan. Sebagai contoh, daripada melaksanakan fungsi yang mengira nilai berulang kali, cuba simpan hasil pengiraan dalam pembolehubah dan gunakannya.

Alat untuk Pemprofilan

Untuk mengetahui lebih lanjut tentang prestasi kod anda, selain pemprofilan terbina dalam, kami boleh menggunakan pakej pemprofilan luaran seperti cProfile, Pyflame atau SnakeViz.

Keputusan Cache

Jika kod kami perlu melakukan pengiraan yang mahal, kami mungkin mempertimbangkan untuk menyimpan cache hasil untuk menjimatkan masa.

Pemfaktoran Semula Kod

Memfaktorkan semula kod untuk menjadikannya lebih mudah dibaca dan diselenggara kadangkala merupakan bahagian yang diperlukan untuk mengoptimumkannya. Program yang lebih pantas juga mungkin lebih bersih.

Gunakan Kompilasi Just-in-Time (JIT)

Perpustakaan seperti PyPy atau Numba boleh menyediakan kompilasi JIT yang boleh mempercepatkan jenis kod Python tertentu dengan ketara.

Tingkatkan Python

Pastikan anda menggunakan versi terkini Python kerana versi yang lebih baharu selalunya menyertakan peningkatan prestasi.

Paralelisme dan Konkurensi

Untuk proses yang boleh disejajarkan, siasat teknik selari dan penyegerakan seperti berbilang pemprosesan, penjalinan atau asyncio.

Ingat bahawa penanda aras dan pemprofilan harus menjadi pemacu utama pengoptimuman. Tumpukan pada meningkatkan bidang kod kami yang mempunyai kesan paling ketara pada prestasi, dan sentiasa menguji peningkatan anda untuk memastikan bahawa ia mempunyai kesan yang diingini tanpa memperkenalkan lebih banyak kecacatan.

Kesimpulan

Kesimpulannya, pengoptimuman kod Python adalah penting untuk meningkatkan prestasi dan keberkesanan sumber. Pembangun boleh meningkatkan kelajuan pelaksanaan dan responsif aplikasi Python mereka dengan banyak menggunakan pelbagai teknik seperti memilih struktur data yang sesuai, memanfaatkan fungsi terbina dalam, mengurangkan gelung tambahan dan mengurus memori dengan berkesan. Penandaarasan dan pemprofilan berterusan harus mengarahkan usaha pengoptimuman, memastikan bahawa kemajuan kod sepadan dengan keperluan prestasi dunia sebenar. Untuk menjamin kejayaan projek jangka panjang dan mengurangkan peluang untuk memperkenalkan masalah baharu, pengoptimuman kod harus sentiasa diseimbangkan dengan objektif kebolehbacaan dan kebolehselenggaraan kod.