Penjelasan Python *args dan **kwargs: Fungsi Fleksibel Dengan Contoh Jelas

  1. Beranda
  2. Blog
  3. Pengembangan Perangkat Lunak

Pengembangan Perangkat Lunak

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.

8 menit baca
Python *args dan **kwargs menjelaskan: fungsi fleksibel dengan contoh yang jelas

Poin penting

  • *args mengumpulkan argumen posisi tambahan ke dalam tuple.
  • **kwargs mengumpulkan 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:

  1. Parameter posisi reguler
  2. *argumen
  3. Parameter khusus kata kunci
  4. **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. Tulis total(*nums).
  • Menelan kesalahan ketik. Fungsi yang menerima **kwargs tetapi mengabaikan kunci yang tidak diketahui menyembunyikan opsi yang salah eja. Validasi, atau hindari **kwargs.
  • Melalui argumen yang sama dua kali. f(1, **{"a": 2}), dengan a adalah parameter pertama, menimbulkan kesalahan “beberapa nilai”.
  • Tidak meneruskan dalam bungkus. Memanggil func(args, kwargs) melewati tuple dan dict. Bentuk yang benar adalah func(*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

Bekerja dengan Stack Quora

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.

Teruslah membaca

Panduan lebih lanjut tentang pengujian, AI & pengembangan modern

Menikmati artikel ini? Pilih topik dan langsung masuk ke tutorial terbaru kami.

Kecerdasan buatan

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 →
DevOps

Penjelasan 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 lunak

Penjelasan 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 pengujian

Mengejek 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 lunak

Penjelasan 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 & SQL

DELETE 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 & SQL

Penjelasan 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 lunak

Antarmuka 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 lunak

Penjelasan 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 lunak

Fungsi 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 buatan

Apa 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 →
DevOps

Pemantauan 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 →
DevOps

Volume 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 pengujian

TDD 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 lunak

Git 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 lunak

List 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 & SQL

Penjelasan 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 →