Penjelasan Python *args dan **kwargs: Fungsi Fleksibel Dengan Contoh Jelas
Bintang-bintang dalam tanda tangan fungsi tidak se-misterius kelihatannya. Pelajari bagaimana *args dan **kwargs mengumpulkan argumen, bagaimana bintang yang sama menguraikannya, dan bagaimana merancang tanda fungsi yang sulit disalahgunakan.
*argsmengumpulkan argumen posisi tambahan ke dalam tuple.**kwargsmengumpulkan argumen kata kunci tambahan ke dalam kamus.- Nama-nama tersebut hanyalah sebuah konvensi, karena
*dan**adalah yang terpenting. - Bintang yang sama unpack daftar atau kamus saat Anda memanggil suatu fungsi.
Cepat atau lambat, Anda akan membaca fungsi seperti def handler(*args, **kwargs) dan bertanya-tanya apa yang diterimanya. Python *args dan **kwargs membiarkan suatu fungsi mengambil sejumlah argumen yang fleksibel. Mereka mendukung dekorator, wrapper, dan banyak API perpustakaan.
Panduan ini mencakup cara kerjanya di kedua arah, bersama dengan cara-cara baru Python memungkinkan Anda mengontrol cara suatu fungsi dipanggil. Kami menjalankan setiap contoh di Python 3.13, dan output yang ditampilkan berasal dari proses tersebut.
Apa yang dilakukan *args
Parameter yang ditulis dengan satu bintang mengumpulkan argumen posisi tambahan apa pun ke dalam sebuah tuple:
def total(*args):
print(type(args).__name__, args)
return sum(args)
print(total(1, 2, 3))
# tuple (1, 2, 3)
# 6
print(total())
# tuple ()
# 0
Tanpa argumen, Anda cukup mendapatkan tupel kosong, sehingga fungsinya tetap berfungsi. Nama args adalah sebuah konvensi. *numbers akan berperilaku sama, dan nama yang lebih deskriptif seringkali lebih baik.
Apa yang **kwarg lakukan
Dua bintang mengumpulkan argumen kata kunci tambahan ke dalam kamus:
def describe(**kwargs):
print(type(kwargs).__name__, kwargs)
describe(name="Asha", city="Pune")
# dict {'name': 'Asha', 'city': 'Pune'}
Karena ini adalah kamus normal, Anda dapat mengulanginya, mencari kunci dengan get() dan menyebarkannya. Kunci menjaga urutan penyampaiannya.
Urutan parameter
Saat Anda mencampur berbagai jenis parameter, Python memerlukan urutan tertentu:
- Parameter posisi reguler
*argumen- Parameter khusus kata kunci
**kwarg
def order(item, qty=1, *extras, priority=False, **notes):
print(item, qty, extras, priority, notes)
order("pen")
# pen 1 () False {}
order("pen", 2, "gift wrap", "card", priority=True, note="leave at door")
# pen 2 ('gift wrap', 'card') True {'note': 'leave at door'}
Pemberitahuan priority. Karena terletak setelah *extras, maka hanya dapat ditetapkan berdasarkan nama, sehingga argumen posisi yang menyimpang tidak akan pernah dapat menetapkannya secara kebetulan. Menempatkan **kwargs sebelumnya tidak diperbolehkan, dan pengujian kami memunculkan SyntaxError: ”argumen tidak dapat mengikuti argumen var-keyword”.
Membongkar saat menelepon
Bintang yang sama bekerja secara terbalik di lokasi panggilan. Satu bintang menyebarkan daftar atau tupel ke dalam argumen posisi, dan dua bintang menyebarkan kamus ke dalam argumen kata kunci:
nums = [4, 5, 6]
total(*nums) # same as total(4, 5, 6) -> 15
settings = {"name": "Ben", "city": "Delhi"}
describe(**settings) # same as describe(name="Ben", city="Delhi")
Pembongkaran dapat dilakukan dengan fungsi apa pun, tidak hanya fungsi yang menggunakan *args dan **kwargs. Itu berguna ketika konfigurasi hadir sebagai kamus:
def connect(host, port, timeout=5):
return f"{host}:{port} (timeout {timeout})"
connect(**{"host": "db.local", "port": 5432})
# 'db.local:5432 (timeout 5)'
connect(**{"host": "db.local", "port": 5432, "ssl": True})
# TypeError: connect() got an unexpected keyword argument 'ssl'
Kesalahan itu berguna. Fungsi tanpa **kwargs menolak opsi yang tidak diketahui, sehingga kesalahan ketik pada nama pengaturan akan gagal dan bukannya diabaikan secara diam-diam.
Argumen khusus kata kunci
Tanda * kosong di tanda tangan, tanpa nama, berarti “segala sesuatu setelah ini harus diteruskan dengan kata kunci”:
def make_user(name, *, admin=False):
return name, admin
make_user("Asha", admin=True)
# ('Asha', True)
make_user("Asha", True)
# TypeError: make_user() takes 1 positional argument but 2 were given
Ini adalah cara terbaik untuk melindungi bendera boolean. Panggilan seperti make_user("Asha", True) memaksa pembaca untuk menebak apa maksud True. Membutuhkan admin=True membuat setiap panggilan menjadi cukup jelas.
Argumen yang hanya bersifat posisi
Sejak Python 3.8, / menandai parameter yang hanya dapat dilewati berdasarkan posisi:
def area(width, height, /):
return width * height
area(3, 4) # 12
area(width=3, height=4)
# TypeError: area() got some positional-only arguments
# passed as keyword arguments: 'width, height'
Hal ini memungkinkan perpustakaan mengganti nama parameter tersebut nanti tanpa merusak kode siapa pun, karena tidak ada yang bisa bergantung pada namanya. Beberapa built-in bekerja dengan cara ini. Misalnya, len(obj=[1]) tidak berfungsi.
Tips: Pola lengkapnya adalah def f(pos_only, /, normal, *, kw_only). Anda jarang membutuhkan ketiganya, tetapi mengetahui apa arti / dan * membantu Anda membaca dokumentasi dan tanda tangan perpustakaan.
Dekorator dan pembungkus
Ini adalah alasan utama dunia nyata untuk menggunakan keduanya secara bersamaan. Wrapper sering kali perlu menerima argumen apa pun yang digunakan fungsi aslinya, dan meneruskannya tanpa perubahan:
import functools, time
def timed(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.perf_counter() - start:.4f}s")
return result
return wrapper
@timed
def slow_add(a, b, delay=0.01):
time.sleep(delay)
return a + b
print(slow_add(2, 3, delay=0.02))
# slow_add took 0.0205s
# 5
Wrapper tidak perlu mengetahui parameter slow_add sama sekali, sehingga dapat berfungsi untuk fungsi apa pun. Angka waktu Anda akan sedikit berbeda. Panduan kami untuk Dekorator Python menjelaskan functools.wraps dan detail lainnya.
Menggabungkan opsi
** juga berfungsi di dalam kamus literal, yang memberikan cara yang rapi untuk menerapkan penggantian di atas default:
defaults = {"theme": "light", "lang": "en"}
def build(**overrides):
return {**defaults, **overrides}
build(theme="dark")
# {'theme': 'dark', 'lang': 'en'}
Kunci selanjutnya menang, jadi override menggantikan default. Subkelas juga menggunakan pola ini, seperti pada super().__init__(*args, **kwargs), untuk meneruskan argumen tambahan ke kelas induk. Lihat Kelas dan objek Python untuk informasi lebih lanjut tentang super().
Lembar contekan
| Sintaks | Dimana | Artinya |
|---|---|---|
def f(*args) |
Definisi | Kumpulkan argumen posisi tambahan ke dalam sebuah tuple |
def f(**kwarg) |
Definisi | Kumpulkan argumen kata kunci tambahan ke dalam dict |
def f(a, *, b) |
Definisi | b hanya untuk kata kunci |
def f(a, /, b) |
Definisi | a hanya untuk posisi saja |
f(*items) |
Telepon | Sebarkan urutan ke dalam argumen posisi |
f(**options) |
Telepon | Sebarkan dict ke dalam argumen kata kunci |
{**a, **b} |
Harafiah | Gabungkan kamus |
[*a, *b] |
Harafiah | Gabungkan iterable ke dalam daftar |
Kapan harus menghindarinya
Fleksibilitas mempunyai harga. Fungsi yang didefinisikan sebagai def create(**kwargs) tidak memberi tahu pembaca apa pun tentang opsi yang ada, dan editor tidak dapat melengkapinya secara otomatis. Kesalahan ketik mungkin terjadi secara diam-diam melalui beberapa lapisan sebelum terjadi kesalahan.
Jadi pilihlah parameter eksplisit ketika Anda mengetahui apa yang dibutuhkan suatu fungsi. Gunakan *args dan **kwargs ketika Anda benar-benar membutuhkan fleksibilitas: wrapper, dekorator, meneruskan argumen ke fungsi lain, atau input panjang variabel sebenarnya seperti total(*numbers). Jika suatu fungsi memerlukan banyak opsi bernama, dataclass juga bisa lebih jelas.
Kesalahan umum
Menggunakan default yang bisa berubah
Ini bukan tentang bintang, tetapi sering kali muncul di dekatnya. Nilai default dibuat satu kali, saat fungsi ditentukan, lalu dibagikan di antara panggilan:
def bad(items=[]):
items.append(1)
return items
print(bad(), bad())
# [1, 1] [1, 1]
Kedua panggilan tersebut mengembalikan daftar yang sama, yang kemudian berisi dua item. Gunakan items=None dan buat daftar baru di dalam fungsi.
Kesalahan lainnya
- Lupa membongkar. Memanggil
total(nums)melewati satu daftar, bukan tiga nomor. Tulistotal(*nums). - Menelan kesalahan ketik. Fungsi yang menerima
**kwargstetapi mengabaikan kunci yang tidak diketahui menyembunyikan opsi yang salah eja. Validasi, atau hindari**kwargs. - Melalui argumen yang sama dua kali.
f(1, **{"a": 2}), denganaadalah parameter pertama, menimbulkan kesalahan “beberapa nilai”. - Tidak meneruskan dalam bungkus. Memanggil
func(args, kwargs)melewati tuple dan dict. Bentuk yang benar adalahfunc(*args, **kwargs).
Ketik petunjuk untuk *args dan **kwargs
Ketik petunjuk pada *args dan **kwargs mendeskripsikan masing-masing nilai individual, bukan keseluruhan koleksi. Hal ini mengejutkan banyak orang:
def total(*prices: float) -> float:
return sum(prices) # prices is tuple[float, ...]
def tag(**attrs: str) -> str:
return " ".join(f'{k}="{v}"' for k, v in attrs.items()) # dict[str, str]
total(1.5, 2.5) # 4.0
tag(id="x", role="button") # id="x" role="button"
Di sini prices diperlakukan sebagai tupel float dan attrs sebagai kamus string. Ketika argumen kata kunci memiliki tipe berbeda, Python 3.12 menambahkan opsi yang tepat: TypedDict dikombinasikan dengan Unpack.
from typing import TypedDict, Unpack
class Options(TypedDict, total=False):
timeout: float
retries: int
def fetch(url: str, **opts: Unpack[Options]) -> None: ...
Pemeriksa tipe seperti mypy atau Pyright kemudian dapat menolak fetch(url, retries="3") atau nama opsi yang salah eja, yang tidak akan pernah bisa dilakukan oleh **kwargs biasa. Namun, perilaku runtime tidak berubah. Ketika kami menjalankan fetch("u", retries="3") di bawah Python 3.13, ia dieksekusi tanpa keluhan, karena Python sendiri tidak menerapkan petunjuk tipe.
Jika Anda mendokumentasikan daftar panjang kunci yang diterima untuk **kwargs, pertimbangkan untuk menggantinya dengan parameter eksplisit khusus kata kunci. Editor kemudian dapat melengkapinya secara otomatis, dan kesalahan akan segera diketahui.
Penutup
Ingat dua arah. Dalam definisinya, bintang dikumpulkan. Dalam panggilan, mereka membongkar. Tambahkan argumen khusus kata kunci untuk membuat panggilan lebih jelas, dan simpan **kwargs untuk kode yang benar-benar meneruskan argumen. Untuk berlatih, tulis dekorator kecil yang mencatat setiap argumen panggilan, dan gunakan pada beberapa fungsi berbeda.
Pertanyaan yang sering diajukan
Apa perbedaan antara *args dan **kwargs?
*args mengumpulkan argumen posisi tambahan ke dalam sebuah Tuple. **kwargs mengumpulkan argumen kata kunci tambahan ke dalam kamus. Suatu fungsi dapat menggunakan keduanya secara bersamaan.
Apakah saya harus menyebutnya args dan kwargs?
Tidak. Bintang-bintang yang melakukan pekerjaannya, jadi *nilai atau **pilihan sama-sama valid. args dan kwargs hanyalah sebuah konvensi yang diakui secara luas.
Urutan apa yang harus *args dan **kwargs masuk?
Parameter reguler terlebih dahulu, lalu *args, lalu parameter khusus kata kunci, dan **kwargs terakhir. Urutan lainnya menyebabkan SyntaxError.
Apa arti * tunggal dalam definisi fungsi?
Tanda * kosong berarti setiap parameter setelahnya harus dilewati dengan kata kunci. Itu membuat panggilan menjadi lebih jelas, terutama untuk flag boolean.
Apa maksud / dalam fungsi Python?
Parameter sebelum / hanya bersifat posisi, sehingga pemanggil tidak dapat meneruskannya berdasarkan nama. Fitur ini ditambahkan di Python 3.8.
Teruslah belajar
Butuh bantuan dengan pengujian, WordPress atau SEO?
Kami membantu tim mengirimkan perangkat lunak yang lebih baik dan mengembangkan situs mereka. Beritahu kami apa yang sedang Anda kerjakan dan kami akan menyarankan langkah selanjutnya yang jelas.
Panduan lebih lanjut tentang pengujian, AI & pengembangan modern
Menikmati artikel ini? Pilih topik dan langsung masuk ke tutorial terbaru kami.
Penjelasan Halusinasi AI: Mengapa Model Bahasa Memperbaiki Masalah dan Cara Menguranginya
Halusinasi AI menjelaskan: apa itu, mengapa model bahasa memproduksinya, tipe umum, cara menguranginya dengan landasan dan petunjuk, dan pemeriksaan…
Baca artikel →DevOpsPenjelasan Variabel Lingkungan: File .env, Rahasia, dan Konfigurasi Dilakukan dengan Benar
Variabel lingkungan dijelaskan dengan contoh Python yang kami jalankan: membaca dan mengaturnya, mengapa setiap nilai berupa string, file .env, pewa…
Baca artikel →Pengembangan perangkat lunakPenjelasan Pembatasan Kecepatan API: Algoritma, Header, dan Penanganan 429 Kesalahan
Pembatasan laju API dijelaskan dengan simulasi yang kami jalankan: keranjang token, jendela tetap, jendela geser, respons 429, header batas laju, pe…
Baca artikel →Otomatisasi pengujianMengejek dengan Python: unittest.mock, patch dan Kesalahan yang Membuat Tes Berbohong
Mengejek dengan Python dengan unittest.mock, menguji: Mock dan return_value, side_effect, menambal di mana nama digunakan, spesifikasi dan autospec,…
Baca artikel →Pengujian perangkat lunakPenjelasan Cakupan Kode: Cakupan Jalur vs Cabang dan Apa Arti 100% Sebenarnya
Cakupan kode dijelaskan dengan coverage.py yang sebenarnya dijalankan: cakupan garis, cabang dan kondisi, membaca laporan, mengapa cakupan 100% masi…
Baca artikel →Basis data & SQLDELETE vs TRUNCATE vs DROP dalam SQL: Perbedaan, Rollback dan Kapan Menggunakan Masing-Masing
DELETE vs TRUNCATE vs DROP dijelaskan dengan SQL yang diuji: apa yang dihapus, rollback, pemicu, reset identitas, kecepatan, dan perbedaan PostgreSQ…
Baca artikel →Basis data & SQLPenjelasan Tampilan SQL: Membuat, Menggunakan, dan Menghindari Kesalahan, Dengan Contoh
Tampilan SQL dijelaskan dengan kueri yang kami jalankan: membuat tampilan, hasil langsung, menyembunyikan kolom, kinerja, tampilan yang dapat diperb…
Baca artikel →Pengembangan perangkat lunakAntarmuka TypeScript vs Tipe: Perbedaan Nyata, Diuji Dengan Kompiler
Antarmuka TypeScript vs tipe, diperiksa dengan kompiler sebenarnya: apa yang bisa dilakukan keduanya, apa yang hanya bisa dilakukan satu orang, peng…
Baca artikel →Pengembangan perangkat lunakPenjelasan Python *args dan **kwargs: Fungsi Fleksibel Dengan Contoh Jelas
Python *args dan **kwargs dijelaskan dengan kode yang kami jalankan: pengepakan dan pembongkaran, urutan parameter, argumen hanya kata kunci dan pos…
Baca artikel →Pengembangan perangkat lunakFungsi Python Lambda: Sintaks, Kegunaan Sebenarnya, dan Kapan Tidak Digunakan
Fungsi python lambda dijelaskan dengan kode yang kami jalankan: sintaksis, pengurutan dengan kunci, peta dan filter, penutupan, jebakan pengikatan a…
Baca artikel →Kecerdasan buatanApa Itu Agen AI? Cara Kerjanya, Dengan Agent Loop Sederhana yang Dapat Anda Jalankan
Apa itu agen AI? Panduan sederhana tentang loop agen, alat, memori, dan pagar pembatas, dengan loop Python kecil yang kami jalankan, risiko nyata da…
Baca artikel →DevOpsPemantauan vs Observabilitas: Perbedaan Nyata, Dengan Log, Metrik, dan Jejak
Penjelasan pemantauan vs observabilitas: kegagalan yang diketahui dan tidak diketahui, log, metrik dan jejak, penelusuran insiden checkout, sinyal e…
Baca artikel →DevOpsVolume Docker vs Bind Mounts: Pertahankan Data Kontainer dengan Cara yang Benar
Volume Docker vs pengikatan pengikat dijelaskan: mengapa data kontainer menghilang, volume yang diberi nama, pengikatan pengikatan, tmpfs, contoh Tu…
Baca artikel →Otomatisasi pengujianTDD vs BDD: Perbedaan Utama, Satu Fitur Dibangun dengan Dua Cara dan Kapan Menggunakan Masing-masing
TDD vs BDD dijelaskan dengan satu fitur diskon yang dibuat dengan dua cara: refactor merah-hijau dengan kode yang kami jalankan, skenario Mengingat-…
Baca artikel →Pengembangan perangkat lunakGit merge vs rebase: perbedaan, contoh, dan kapan memakai masing-masing
Git merge vs rebase dijelaskan dengan keluaran log nyata, tabel perbandingan, aturan emas rebase, dan alur kerja tim yang aman.
Baca artikel →Pengembangan perangkat lunakList Comprehension Python: Sintaks, Contoh, dan Kapan Harus Dihindari
List comprehension Python dijelaskan: sintaks, filter, if-else, perulangan bersarang, waktu yang diukur, dan kapan perulangan for biasa lebih baik.
Baca artikel →Basis data & SQLPenjelasan SQL JOIN dengan Contoh (Inner, Left, Right, Full)
Pahami SQL JOIN langkah demi langkah dengan tabel dan query contoh: INNER, LEFT, RIGHT, FULL, CROSS, dan SELF, plus kesalahan umum dan tips performa.
Baca artikel →