Baris paling aneh di Python, dijelaskan
Buka hampir semua file Python dan cepat atau lambat kamu akan melihat ini di bagian bawah:
if __name__ == "__main__":
main()
Kelihatannya seperti boilerplate ajaib. Sebenarnya ini fitur yang sangat praktis begitu kamu tahu fungsinya, dan fitur ini ada karena Python tidak membedakan "skrip" dan "library".
Situasinya: dua cara memakai sebuah file
Setiap file .py di Python bisa dipakai dengan dua cara berbeda:
- Sebagai skrip: kamu menjalankannya langsung dengan
python3 file.py. - Sebagai module: file lain meng-import-nya dengan
import file.
Bahasanya tidak memintamu menyatakan mana yang sedang kamu tulis. File apa pun bisa saja melakukan keduanya.
Misalnya ada file bernama math_helpers.py:
# math_helpers.py
def mean(values):
return sum(values) / len(values)
def median(values):
s = sorted(values)
mid = len(s) // 2
if len(s) % 2 == 0:
return (s[mid - 1] + s[mid]) / 2
return s[mid]
# Quick smoke test while developing
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print("mean:", mean(numbers))
print("median:", median(numbers))
Kalau kamu menjalankan file ini langsung, ia mencetak output ujinya, bagus. Tapi kalau ada file lain yang menjalankan import math_helpers, pernyataan print itu ikut berjalan saat import. Setiap pengguna module itu melihat output coba-cobamu selama pengembangan. Tidak bagus.
Apa itu __name__
Setiap module Python punya variabel bawaan bernama __name__. Python mengaturnya secara otomatis:
- Saat file di-import,
__name__diisi nama import module tersebut, yaitu"math_helpers"pada contoh di atas. - Saat file dijalankan langsung, Python mengisi
__name__dengan string khusus"__main__".
Dari situ kamu bisa tahu sedang berada di mode yang mana. Bungkus kode "khusus skrip" dengan sebuah pengecekan:
# math_helpers.py
def mean(values):
return sum(values) / len(values)
def median(values):
s = sorted(values)
mid = len(s) // 2
if len(s) % 2 == 0:
return (s[mid - 1] + s[mid]) / 2
return s[mid]
if __name__ == "__main__":
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print("mean:", mean(numbers))
print("median:", median(numbers))
Sekarang python3 math_helpers.py mencetak output ujinya. Tapi import math_helpers dari file lain melewati blok itu sepenuhnya: fungsinya tetap tersedia, dan tidak ada yang berjalan tanpa diminta.
Pasangan yang umum: fungsi main()
Kebanyakan skrip sungguhan akhirnya punya fungsi main() sendiri dan menjaga blok guard tetap kecil:
# process_orders.py
import sys
def load_orders(path):
with open(path) as f:
return [line.strip() for line in f if line.strip()]
def process(orders):
for order in orders:
print(f"Processing {order}")
def main():
if len(sys.argv) < 2:
print("Usage: python3 process_orders.py <file>")
sys.exit(1)
orders = load_orders(sys.argv[1])
process(orders)
if __name__ == "__main__":
main()
Kenapa repot memakai main() alih-alih menaruh logikanya langsung di bawah guard if?
- Mudah diuji. Kamu bisa meng-import module-nya lalu memanggil
main()(atau fungsi pembantu mana pun) dari test. - Variabel lokal. Apa pun yang didefinisikan di dalam
main()adalah variabel lokal, bukan nama di level module. Itu mencegah bentrok nama yang tidak disengaja dan membuat bagian publik module lebih rapi. - Mudah dibaca. Blok guard kini hanya dua baris, sebuah "titik masuk skrip" yang jelas, bukan tumpukan logika.
Demonstrasi singkat
Kamu bisa melihat perilakunya secara langsung:
Saat kamu menjalankan potongan kode di atas dengan Python, ia mencetak __name__ is: __main__ dan "being run as a script." Kalau ada file lain yang meng-import file ini, pengecekan yang sama akan mencetak cabang yang satunya.
Saat kamu tidak butuh guard
Banyak file Python yang tidak pernah memakainya. Skrip pendek yang tidak akan pernah di-import siapa pun tidak masalah tanpa guard:
# one_off_rename.py
import os
for name in os.listdir("."):
if name.endswith(".txt"):
os.rename(name, name.lower())
Itu sudah benar. Kamu tidak sedang membangun library; tidak akan ada yang meng-import file ini. Tapi begitu sebuah file berisi logika yang bisa dipakai ulang, dan kamu ingin tetap menyimpan kode yang punya efek samping di sampingnya, pakailah guard.
Entry point untuk package yang di-install
Begitu kamu menerbitkan kodemu sebagai package sungguhan, ada mekanisme yang lebih formal: entry_points di metadata package-mu, yang memetakan sebuah perintah ke sebuah fungsi. Pengguna yang meng-install package-mu mendapat perintah shell yang langsung memanggil fungsi itu. Tapi untuk skrip yang dijalankan dari sebuah folder di komputermu sendiri, guard __main__ adalah alat standarnya.
Rangkuman bab ini
Sekarang kamu sudah punya:
- Fungsi untuk memberi nama pada logikamu.
*args/**kwargsuntuk pemanggilan yang fleksibel.- Lambda untuk fungsi sekali pakai.
- Decorator dan type hint untuk membungkus dan mendokumentasikan fungsi-fungsi itu.
- Module, pip, dan virtual environment untuk membagi kode ke beberapa file dan proyek.
- Guard
__main__agar skrip dan module bisa hidup berdampingan.
Berikutnya: class
Sejauh ini kamu kebanyakan memasangkan fungsi dengan data biasa: dict, list, tuple. Bab berikutnya memperkenalkan class, cara Python menyatukan data dan perilaku, sekaligus tempat konsep seperti self, __init__, pewarisan (inheritance), dan dataclass berada.
Pertanyaan yang sering diajukan
Apa fungsi if __name__ == '__main__'?
Blok di bawahnya hanya dijalankan saat file dieksekusi langsung (bukan saat file di-import sebagai module). Dengan begitu kamu bisa menulis file .py yang bisa dijalankan sebagai skrip atau di-import untuk mengambil fungsi dan class-nya, tanpa aksi skripnya ikut berjalan saat import.
Apakah Python butuh fungsi main?
Tidak. File Python otomatis berjalan dari atas ke bawah. Tapi begitu sebuah file berisi logika yang juga ingin bisa di-import, guard if __name__ == '__main__' menjadi penting. Kebiasaan yang sering menyertainya adalah menaruh pekerjaan utama skrip di dalam fungsi main().
Apa bedanya __name__ dan __main__?
__name__ adalah variabel khusus yang diatur Python di setiap module. Jika file di-import, __name__ berisi nama module-nya (misalnya 'util'). Jika file dijalankan langsung, Python mengatur __name__ menjadi string '__main__'. Pengecekan if membandingkan keduanya.