Learning Python - Advanced Functions & Functional Tools
Episode 4 of 23

Learning Python - Advanced Functions & Functional Tools

This episode deepens your Python functions: positional and keyword arguments, *args and **kwargs, and the mutable default trap. You'll also learn higher-order functions, lambda, the functools module for partial and lru_cache, and iterator utilities.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

In episode 3 we got to know basic functions. Episode 4 takes you deeper: how Python functions actually behave in the real world — including the hidden traps that can make your code behave strangely.

We'll cover flexible arguments with *args and **kwargs, the famous mutable default trap, higher-order functions, lambda, the functools module, and iterator utilities. These skills are what separate an ordinary Python programmer from a skilled one.

Positional and Keyword Arguments

Understanding *args

*args captures a flexible number of positional arguments as a tuple:

PythonMenggunakan *args
def jumlahkan(*args):
    return sum(args)
 
print(jumlahkan(1, 2, 3))
print(jumlahkan(10, 20))

The call jumlahkan(1, 2, 3) gathers all positional arguments into a tuple args. This is useful when the number of arguments isn't fixed, like a log function that accepts any number of messages.

Understanding **kwargs

**kwargs captures flexible keyword arguments as a dict:

PythonMenggunakan **kwargs
def cetak_profil(**kwargs):
    for kunci, nilai in kwargs.items():
        print(f"{kunci}: {nilai}")
 
cetak_profil(nama="Arman", peran="Engineer", tim="Platform")

The call cetak_profil(nama="Arman", peran="Engineer") gathers keyword arguments into a dict. **kwargs is very commonly used to forward configuration options without declaring every parameter.

The Mutable Default Trap

The Problem with a List as Default

A classic Python trap is using a mutable object as a default value. Defaults are evaluated once when the function is defined, not on every call:

PythonJebakan default mutable
def tambah(item, daftar=[]):
    daftar.append(item)
    return daftar
 
print(tambah(1))
print(tambah(2))

The second call to tambah(2) outputs [1, 2], not [2]! Because daftar=[] is created once and shared across calls. This is a well-known bug that's hard to track down.

The None Solution

The standard solution is to use None as the default and create a new object inside the function:

PythonSolusi default mutable
def tambah(item, daftar=None):
    if daftar is None:
        daftar = []
    daftar.append(item)
    return daftar
 
print(tambah(1))
print(tambah(2))

The pattern if daftar is None: daftar = [] guarantees a new object is created on every call. The golden rule: never use a list, dict, or set as a default parameter.

Higher-Order Functions

Functions That Accept Functions

Python treats functions as first-class objects: functions can be stored, passed as arguments, and returned. A function that accepts or returns functions is called a higher-order function:

PythonHigher-order function
def terapkan(fungsi, nilai):
    return fungsi(nilai)
 
def kali_dua(x):
    return x * 2
 
print(terapkan(kali_dua, 5))

The call terapkan(kali_dua, 5) passes the function kali_dua as an argument. This pattern is the foundation of many functional programming techniques and is widely used in libraries like pandas and Django.

Lambda: Anonymous Functions

A lambda is a one-line anonymous function for simple cases:

PythonLambda expression
kuadrat = lambda x: x * x
print(kuadrat(7))
 
data = [(1, "apel"), (3, "ceri"), (2, "mangga")]
data.sort(key=lambda pasangan: pasangan[1])
print(data)

lambda x: x * x defines a function without a name. When sorting, data.sort(key=lambda pasangan: pasangan[1]) sorts by the second element. Use lambda for short logic; for complex logic, define a named function.

The functools Module

partial to Lock Arguments

functools.partial locks part of a function's arguments into a new function:

PythonMenggunakan partial
from functools import partial
 
def pangkat(eksponen, basis):
    return basis ** eksponen
 
kuadrat = partial(pangkat, 2)
print(kuadrat(5))

partial(pangkat, 2) creates a new function that already locks in eksponen=2. Calling kuadrat(5) is equivalent to pangkat(2, 5). This is useful for building specialized functions from general ones.

lru_cache for Memoization

lru_cache stores function call results so repeated calls with the same arguments become instant:

PythonMemoisasi dengan lru_cache
from functools import lru_cache
 
@lru_cache(maxsize=128)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)
 
print(fibonacci(30))

The decorator @lru_cache(maxsize=128) adds caching to the fibonacci function. Without caching, the 30th calculation repeats millions of times; with caching, every value is computed once. This memoization is very effective for recursive functions and repeated queries.

Iterator Utilities

The itertools Module

The itertools module provides efficient iterator-building functions. Some of the most useful ones:

PythonUtilitas itertools
from itertools import chain, islice, cycle
 
angka = [1, 2, 3]
huruf = ["a", "b"]
 
print(list(chain(angka, huruf)))
print(list(islice(cycle(angka), 5)))

chain(angka, huruf) concatenates iterables into one. islice(cycle(angka), 5) cycles an iterable infinitely, then slices the first five elements. These utilities are memory-efficient because they all work lazily.

Closing

Key takeaways:

  • *args captures flexible positional arguments as a tuple.
  • **kwargs captures flexible keyword arguments as a dict.
  • Never use a mutable object as a default parameter.
  • A higher-order function accepts or returns functions.
  • Lambda is an anonymous function for short logic.
  • functools provides partial and lru_cache for optimization.

In the next episode, episode 5, we'll cover advanced data types and collections — the collections module with deque, defaultdict, Counter, and namedtuple, typing basics, and memory and performance considerations of data structures. You'll learn to pick the right data structure for real problems!

Learning Python - Advanced Functions & Functional Tools | Learn Python