# Fungsi di Python: def, return, argumen, *args dan **kwargs, lambda dan anotasi tipe

URL: https://skillaria.top/id/guides/python/fungsi-python

Fungsi di Python adalah blok kode bernama yang dideklarasikan dengan kata kunci def, dipanggil dengan nama dan tanda kurung, dan mengembalikan hasil lewat return; tanpa return, fungsi mengembalikan None. Argumen diberikan menurut urutan atau nama, *args mengumpulkan nilai posisional tambahan menjadi tuple, **kwargs mengumpulkan argumen bernama menjadi dict, dan lambda membuat fungsi anonim pendek dari satu ekspresi.

Fungsi di Python adalah potongan kode bernama yang bisa dipanggil berkali-kali dengan data masukan yang berbeda. Ia dideklarasikan dengan kata `def`, menerima nilai lewat parameter, dan mengembalikan hasil dengan `return`. Fungsi adalah cara utama untuk mengubah skrip panjang menjadi langkah-langkah yang jelas dan bisa diuji.

## Cara mendeklarasikan fungsi: def python

Deklarasi fungsi diawali `def`, lalu nama, parameter dalam kurung, dan titik dua. Isinya ditulis menjorok empat spasi — indentasi di Python bukan hiasan, melainkan bagian dari sintaks.

```
def greet(name):
    """Mengembalikan sapaan untuk pengguna."""
    return f"Halo, {name}!"

print(greet("Rina"))   # Halo, Rina!
```

String dengan tanda kutip tiga tepat setelah judul disebut docstring, yaitu dokumentasi fungsi. Ia ditampilkan oleh `help(greet)` dan oleh petunjuk di editor. Menurut konvensi PEP 8, nama fungsi ditulis dalam snake_case: `add_expense`, `get_rate`.

Baris `def greet(name):` disebut signature fungsi: nama plus daftar parameter (dan anotasinya jika ada). Dari signature, pembaca langsung paham cara memanggil fungsi tanpa melihat isinya.

## Apa yang dilakukan return di Python

`return` mengakhiri fungsi dan memberikan nilai kepada pemanggilnya. Kode setelah `return` yang sudah dijalankan tidak akan dieksekusi. Jika tidak ada `return`, atau ditulis tanpa nilai, fungsi mengembalikan `None`.

```
def area(w, h):
    w * h          # hasilnya dihitung lalu dibuang

print(area(3, 4))  # None

def area(w, h):
    return w * h

print(area(3, 4))  # 12
```

Lupa menulis `return` adalah salah satu kesalahan paling umum pemula: fungsinya «jalan», tetapi mengembalikan `None`, dan masalahnya baru terasa di baris berikutnya. Fungsi juga bisa mengembalikan beberapa nilai — sebenarnya itu satu tuple yang mudah dibongkar:

```
def min_max(numbers):
    return min(numbers), max(numbers)

low, high = min_max([4, 1, 9])
print(low, high)   # 1 9
```

Return dini membantu mengurangi lapisan bersarang: kasus khusus disingkirkan dulu, baru logika utama ditulis.

```
def discount(price, is_member):
    if price  limit    # membaca global — boleh

def raise_limit():
    global limit
    limit = 2000             # tanpa global, akan terbentuk variabel lokal baru
```

Dalam praktiknya, hindari `global`: fungsi yang mengubah keadaan di luar dirinya sulit diuji. Lebih baik terima nilai lewat argumen dan kembalikan hasilnya.

## Fungsi bersarang dan closure

Fungsi bisa dideklarasikan di dalam fungsi lain. Fungsi bersarang melihat variabel fungsi luarnya bahkan setelah fungsi luar selesai — inilah yang disebut closure. Untuk mengubah variabel seperti itu digunakan `nonlocal`.

```
def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

c = make_counter()
print(c(), c(), c())   # 1 2 3
```

Closure menjadi dasar decorator dan pabrik fungsi.

## Fungsi juga objek

Di Python, fungsi adalah objek biasa: bisa disimpan di variabel, dikirim ke fungsi lain, dikembalikan dari fungsi, atau disimpan di dict. Fungsi punya atribut seperti `__name__`, `__doc__`, `__defaults__`, dan `__annotations__`.

```
def double(x):
    return x * 2

f = double
print(f(5), f.__name__)                # 10 double
print(list(map(double, [1, 2, 3])))   # [2, 4, 6]
```

## Lambda di Python: fungsi anonim

Fungsi lambda adalah fungsi pendek tanpa nama yang badannya hanya satu ekspresi. Hasil ekspresi dikembalikan secara otomatis, sehingga `return` tidak ditulis.

```
square = lambda x: x ** 2
print(square(4))   # 16

expenses = [("Kopi", 250), ("Taksi", 600), ("Makan siang", 450)]
expenses.sort(key=lambda e: e[1], reverse=True)
print(expenses)  # [('Taksi', 600), ('Makan siang', 450), ('Kopi', 250)]

print(list(filter(lambda n: n % 2 == 0, range(10))))  # [0, 2, 4, 6, 8]
```

Lambda cocok sebagai argumen singkat untuk `sorted`, `max`, `map`, dan `filter`. Menyimpan lambda ke variabel seperti `square` di atas tidak dianjurkan PEP 8: jika fungsi perlu nama, tulis `def` — ia akan punya `__name__` yang normal di traceback dan tempat untuk docstring.

|  | def | lambda |
| --- | --- | --- |

| Nama | ada | tidak ada (`<lambda>`) |

| Badan | sejumlah instruksi | satu ekspresi |

| return | eksplisit | implisit |

| Docstring, anotasi | ada | tidak |

| Cocok untuk | segala keperluan | key atau callback singkat |

## Anotasi tipe: petunjuk, bukan pemeriksaan

Anotasi menjelaskan tipe parameter dan hasil yang diharapkan. Python sendiri tidak memeriksanya saat program berjalan: fungsi dengan `x: int` tetap menerima string. Pemeriksaan dilakukan oleh alat luar — mypy, pyright, ty — dan oleh editor yang menyoroti kesalahan sebelum program dijalankan.

```
def add_expense(title: str, amount: float, category: str = "lainnya") -> dict[str, object]:
    return {"title": title, "amount": amount, "category": category}

def area(w: float, h: float) -> float:
    w * h   # mypy: Missing return statement
```

Pemeriksaan bisa dijalankan tanpa instalasi dengan `uvx mypy .`. Contoh di atas memperlihatkan manfaat anotasi: return yang terlupa pada fungsi `-> float` langsung tertangkap analisis.

Sejak Python 3.12 (PEP 695), fungsi generik ditulis tanpa `TypeVar`: parameter tipe ditulis dalam kurung siku, dan alias tipe dideklarasikan dengan kata `type`.

```
def first[T](xs: list[T]) -> T:
    return xs[0]

type Money = int | float
```

Di Python 3.14 (PEP 649) anotasi menjadi malas: ia dievaluasi saat pertama kali diakses, sehingga merujuk kelas yang dideklarasikan di bawah bisa dilakukan tanpa tanda kutip, dan `from __future__ import annotations` tidak lagi diperlukan.

## «Tidak diberikan» atau «diberikan None»: sentinel di 3.15

Nilai bawaan `None` tidak memungkinkan kita membedakan «argumen tidak diberikan» dan «sengaja diberikan None». Bertahun-tahun masalah ini diselesaikan dengan penanda buatan sendiri:

```
_MISSING = object()

def get_rate(currency, default=_MISSING):
    rates = {"USD": 90.5}
    if currency in rates:
        return rates[currency]
    if default is _MISSING:
        raise KeyError(currency)
    return default
```

Di Python 3.15 hadir fungsi bawaan `sentinel` (PEP 661): `MISSING = sentinel("MISSING")` membuat penanda unik dengan repr yang jelas, yang tetap sama saat disalin, bisa di-serialisasi lewat pickle, dan bisa dipakai dalam anotasi seperti `float | MISSING`. Di versi lama, pola dengan `object()` tetap berfungsi.

## Kesalahan umum dengan fungsi

- **Lupa return** — fungsi mengembalikan `None`.
- **Lupa tanda kurung** — `print(greet)` menampilkan objek fungsi, bukan hasil pemanggilan.
- **Nilai bawaan yang bisa diubah** — satu list dipakai bersama oleh semua pemanggilan.
- **Jumlah argumen salah** — `TypeError: greet() missing 1 required positional argument: 'name'`.
- **Nama bertabrakan dengan bawaan** — fungsi bernama `list` atau `sum` akan menutupi fungsi bawaan.

## Ringkasan

Fungsi di Python dideklarasikan dengan `def`, mengembalikan hasil lewat `return`, dan menerima argumen menurut urutan atau nama. `*args` dan `**kwargs` memberi fleksibilitas, `/` dan `*` memberi ketegasan pada pemanggilan, lambda memberi keringkasan untuk fungsi sekali pakai, dan anotasi tipe bersama mypy menangkap kesalahan sebelum program dijalankan. Dalam kursus Python, topik ini dipraktikkan dengan cara memecah pencatat pengeluaran menjadi fungsi-fungsi beranotasi yang diperiksa mypy.

## FAQ

**Apa beda parameter dan argumen?**

Parameter adalah nama di deklarasi fungsi, argumen adalah nilai konkret yang diberikan saat pemanggilan. Pada def greet(name), name adalah parameter; pada greet("Rina"), string "Rina" adalah argumen.

**Bisakah fungsi dipanggil sebelum dideklarasikan?**

Di tingkat modul tidak bisa: baris def harus sudah dieksekusi sebelum pemanggilan, jika tidak akan terjadi NameError. Namun di dalam fungsi lain, kita bisa memanggil fungsi yang dideklarasikan di bawahnya, asalkan pemanggilan terjadi setelah deklarasinya dieksekusi.

**Berapa banyak nilai yang bisa dikembalikan fungsi?**

Secara formal satu, tetapi nilai itu bisa berupa tuple: return a, b mengembalikan tuple berisi dua elemen, yang bisa dibongkar menjadi x, y = f().

**Apakah anotasi tipe wajib?**

Tidak, Python berjalan tanpa anotasi. Namun pada kode yang dibaca orang lain, anotasi memudahkan perawatan dan memungkinkan mypy atau pyright menemukan kesalahan sebelum program dijalankan.

**Bisakah lambda memakai if?**

Hanya ekspresi kondisional: lambda x: "genap" if x % 2 == 0 else "ganjil". Instruksi, perulangan, dan penugasan tidak diperbolehkan di dalam lambda.


---
Source: Skillaria.Top (https://skillaria.top)
