# Mga function sa Python: def, return, argumento, *args at **kwargs, lambda, at type annotation

URL: https://skillaria.top/tl/guides/python/function-sa-python-def

Ang function sa Python ay pinangalanang bloke ng code na idinedeklara gamit ang def, tinatawag sa pamamagitan ng pangalan at mga panaklong, at nagbabalik ng resulta gamit ang return; kapag walang return, nagbabalik ito ng None. Ipinapasa ang mga argumento ayon sa pagkakasunod o ayon sa pangalan, kinokolekta ng *args ang mga dagdag na positional na halaga sa tuple, ng **kwargs ang mga dagdag na keyword sa dictionary, at ang lambda ay gumagawa ng maikling anonymous function mula sa iisang ekspresyon.

Ang function sa Python ay bahagi ng code na may pangalan, na maaaring tawagin nang maraming beses na may iba't ibang input. Idinedeklara ito gamit ang salitang `def`, tumatanggap ng mga halaga sa pamamagitan ng mga parameter, at nagbibigay ng resulta gamit ang `return`. Ang mga function ang pangunahing paraan para gawing malinaw at nasusubok na mga hakbang ang mahabang script.

## Paano magdeklara ng function: def sa Python

Nagsisimula ang deklarasyon ng function sa `def`, sinusundan ng pangalan, mga parameter sa loob ng panaklong, at tutuldok. Ang katawan ay isinusulat na may indentation na apat na espasyo — hindi palamuti ang indentation sa Python, kundi bahagi ng sintaks.

```
def greet(name):
    """Nagbabalik ng pagbati para sa user."""
    return f"Kumusta, {name}!"

print(greet("Anna"))   # Kumusta, Anna!
```

Ang string na nasa triple quote kaagad pagkatapos ng header ay docstring, ang dokumentasyon ng function. Ito ang ipinapakita ng `help(greet)` at ng mga suhestiyon ng editor. Ayon sa PEP 8, isinusulat sa snake_case ang mga pangalan ng function: `add_expense`, `get_rate`.

Ang linyang `def greet(name):` ay tinatawag na signature ng function: pangalan kasama ang listahan ng mga parameter (at mga annotation, kung meron). Sa pamamagitan ng signature, nauunawaan ng nagbabasa kung paano ito tatawagin nang hindi tinitingnan ang katawan.

## Ano ang ginagawa ng return sa Python

Tinatapos ng `return` ang function at ibinibigay ang halaga sa tumawag dito. Hindi na tatakbo ang code pagkatapos ng `return` na naisagawa na. Kapag walang `return` o walang halaga ang `return`, magbabalik ang function ng `None`.

```
def area(w, h):
    w * h          # kinalkula ang resulta at itinapon

print(area(3, 4))  # None

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

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

Ang nakalimutang `return` ay isa sa pinakakaraniwang pagkakamali ng baguhan: "gumagana" ang function, pero `None` ang ibinabalik nito, at lumilitaw ang error sa susunod na linya. Puwede ring magbalik ng ilang halaga — sa totoo, iisang tuple ito na madaling i-unpack:

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

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

Nakatutulong ang maagang `return` na maiwasan ang sobrang nesting: unang inaalis ang mga espesyal na kaso, saka isinusulat ang pangunahing lohika.

```
def discount(price, is_member):
    if price  limit    # pagbasa ng global — puwede

def raise_limit():
    global limit
    limit = 2000             # kung wala ang global, magkakaroon ng lokal na variable
```

Sa praktika, mas mabuting iwasan ang `global`: mahirap subukan ang function na nagbabago ng panlabas na estado. Mas mainam na tumanggap ng halaga bilang argumento at magbalik ng resulta.

## Nested na function at closure

Maaaring ideklara ang function sa loob ng isa pang function. Nakikita ng nested na function ang mga variable ng panlabas kahit tapos na ang panlabas — ito ang tinatawag na closure. Para baguhin ang ganitong variable, ginagamit ang `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
```

Nakabatay ang mga decorator at mga factory ng function sa mga closure.

## Ang function ay isa ring object

Sa Python, ordinaryong object ang function: maaaring ilagay sa variable, ipasa sa ibang function, ibalik mula sa function, o itago sa dictionary. May mga attribute ito: `__name__`, `__doc__`, `__defaults__`, `__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 sa Python: mga anonymous function

Ang lambda function ay maikling function na walang pangalan, at ang katawan nito ay iisang ekspresyon. Awtomatikong ibinabalik ang resulta ng ekspresyon, kaya hindi na isinusulat ang `return`.

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

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

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

Angkop ang lambda bilang maikling argumento ng `sorted`, `max`, `map`, at `filter`. Hindi inirerekomenda ng PEP 8 ang pag-assign ng lambda sa variable, gaya ng `square` sa itaas: kung kailangan ng function ng pangalan, isulat gamit ang `def` — magkakaroon ito ng tamang `__name__` sa traceback at puwang para sa docstring.

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

| Pangalan | mayroon | wala (`<lambda>`) |

| Katawan | anumang bilang ng pahayag | iisang ekspresyon |

| return | tahasan | hindi tahasan |

| Docstring, annotation | oo | hindi |

| Saan angkop | saanman | maikling key o callback |

## Type annotation: mga pahiwatig, hindi pagsusuri

Inilalarawan ng annotation ang inaasahang uri ng mga parameter at ng resulta. Hindi sinusuri ng Python ang mga ito habang tumatakbo: tatanggapin ng function na may `x: int` ang string nang walang problema. Ang mga panlabas na kasangkapan — mypy, pyright, ty — at ang editor na nagpapakita ng error bago pa patakbuhin ang code ang nagsusuri nito.

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

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

Maaaring patakbuhin ang pagsusuri nang walang pag-install gamit ang `uvx mypy .`. Ipinapakita ng halimbawa sa itaas ang kapakinabangan ng annotation: ang nakalimutang `return` sa `-> float` ay agad na nahuhuli ng analyzer.

Mula Python 3.12 (PEP 695), isinusulat ang generic na function nang walang `TypeVar`: inilalagay ang type parameter sa square bracket, at idinedeklara ang alias ng uri gamit ang salitang `type`.

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

type Money = int | float
```

Sa Python 3.14 (PEP 649), naging lazy ang mga annotation: kinakalkula ang mga ito sa unang pagkakataong gamitin, kaya maaaring tukuyin ang klase na idineklara sa ibaba nang walang quote, at hindi na kailangan ang `from __future__ import annotations`.

## "Hindi ipinasa" o "ipinasa ang None": sentinel sa 3.15

Hindi natutukoy ng `None` bilang default kung hindi ipinasa ang argumento o sinadyang ipinasa ang None. Sa loob ng maraming taon, sinosolusyunan ito gamit ang sariling placeholder:

```
_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
```

Sa Python 3.15, lumitaw ang built-in na function na `sentinel` (PEP 661): ang `MISSING = sentinel("MISSING")` ay gumagawa ng natatanging marker na may malinaw na repr, nananatili ang sarili nitong anyo kapag kinopya, nae-serialize gamit ang pickle, at magagamit sa annotation gaya ng `float | MISSING`. Sa mas lumang bersyon, gumagana pa rin ang paraan gamit ang `object()`.

## Karaniwang pagkakamali sa mga function

- **Nakalimutan ang return** — `None` ang ibinabalik ng function.
- **Nakalimutan ang panaklong** — ang `print(greet)` ay magpi-print ng object ng function, hindi ng resulta ng tawag.
- **Mutable na default na halaga** — iisang listahan para sa lahat ng tawag.
- **Maling bilang ng argumento** — `TypeError: greet() missing 1 required positional argument: 'name'`.
- **Pangalang kapareho ng built-in** — ang function na `list` o `sum` ay tatakpan ang built-in.

## Buod

Idinedeklara ang mga function sa Python gamit ang `def`, nagbabalik ng resulta gamit ang `return`, at tumatanggap ng argumento ayon sa pagkakasunod o pangalan. Nagbibigay ng kakayahang umangkop ang `*args` at `**kwargs`, ng higpit sa tawag ang `/` at `*`, ng pagiging maikli ang lambda kapag kailangan ng isang beses na function, at ang type annotation kasama ng mypy ay humuhuli ng error bago patakbuhin. Tinatalakay ito nang praktikal sa kurso ng Python: hinahati ang tagasubaybay ng gastos sa mga function na may annotation at sinusuri gamit ang mypy.

## FAQ

**Ano ang pagkakaiba ng parameter at argumento?**

Ang parameter ay pangalan sa deklarasyon ng function, at ang argumento ay partikular na halagang ipinasa sa pagtawag. Sa def greet(name), ang name ay parameter; sa greet("Anna"), ang string na "Anna" ay argumento.

**Maaari bang tawagin ang function bago ito ideklara?**

Sa antas ng module, hindi — dapat naisagawa muna ang linyang def bago ang tawag, kung hindi ay NameError. Pero sa loob ng ibang function, puwedeng tawagin ang function na nasa ibaba, basta mangyari ang tawag pagkatapos ng deklarasyon nito.

**Ilang halaga ang maibabalik ng function?**

Pormal, isa lang, pero puwede itong tuple: ang return a, b ay nagbabalik ng tuple na may dalawang elemento, na maaaring i-unpack bilang x, y = f().

**Kailangan ba talagang maglagay ng type annotation?**

Hindi, gumagana ang Python nang wala ito. Pero sa code na binabasa ng ibang tao, malaki ang naitutulong ng annotation sa maintenance, at nahuhuli ng mypy o pyright ang mga error bago patakbuhin.

**Maaari bang maglagay ng if sa lambda?**

Maaari lang ang conditional expression: lambda x: "pares" if x % 2 == 0 else "di-pares". Hindi pinapayagan sa loob ng lambda ang mga pahayag, loop, at assignment.


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