Lewati ke konten utama

Python reduce(): Panduan Lengkap

Pelajari kapan dan bagaimana menggunakan reduce() di Python. Termasuk contoh praktis dan praktik terbaik.
Diperbarui 28 Sep 2026  · 11 mnt Baca

Jelajahi bersama AI

ChatGPTClaudePerplexity

Fungsi reduce() di Python berakar dari dunia pemrograman fungsional. Pemrograman fungsional (FP) adalah paradigma pemrograman di mana program menghasilkan hasil dengan menerapkan fungsi pada data yang tidak dapat diubah. 

Pola umum dalam gaya ini adalah "fold," yang meruntuhkan sebuah urutan menjadi satu hasil. Misalnya, mem-fold daftar angka [2, 4, 5, 3] dengan operasi penjumlahan menghasilkan 14 melalui langkah berturut-turut: [2, 4, 5, 3] → [6, 5, 3] → [11, 3] → 14.

reduce() menggeneralisasi gagasan ini. Ia menerapkan operasi biner pada sebuah iterable hingga hanya tersisa hasil akhirnya.

Dalam artikel ini, saya akan membahas elemen kunci dari reduce() di Python dan memberikan beberapa contoh praktis. Jika Anda perlu penyegaran dasar-dasar Python, saya sarankan meninjau sumber berikut:

Sejarah

Python menyertakan fungsi pemrograman fungsional lain di Python, seperti map() dan filter(). 

Konstruk fungsional seperti map() dan filter() sudah ada di Python 1.0. Guido van Rossum kurang menyukainya, menyoroti bahwa reduce() sulit dibaca, dan for loop hampir selalu lebih mudah dipahami. Di Python 3.0, mengikuti PEP 3100, pengembang menghapus reduce() sebagai built-in dan memindahkannya ke modul functools. Pemindahan ke functools pada dasarnya menurunkannya menjadi alat untuk kasus khusus.

Mengapa Menggunakan reduce()?

Sebagian besar waktu, menurut saya pilihan yang lebih baik adalah menggunakan built-in atau loop. Namun, reduce() tetap menjadi pilihan yang baik dalam beberapa kasus penggunaan.

  • Pipa fungsi. Merangkai serangkaian transformasi (mungkin dinamis) dengan cara yang rapi.
  • Fold aljabar. Gunakan untuk operasi yang memiliki nilai identitas alami, seperti union himpunan dengan himpunan kosong atau operasi bitmask dengan nol.
  • Fold kustom tanpa built-in. Definisikan penggabungan sendiri secara spesifik domain saat tidak ada built-in yang tersedia.
  • Akumulator terstruktur. Lacak beberapa potongan state secara bersamaan di dalam satu fungsi akumulator kustom.

Cara Kerja reduce() di Python

Mari kita telusuri mekanisme reduce().

Tanda tangan fungsi dasar dari reduce() adalah 

functools.reduce(function, iterable, [initializer])

Fungsi reduce() menerima dua argumen wajib dan satu argumen opsional.

  • function: fungsi biner yang menentukan cara menggabungkan dua elemen,
  • iterable: urutan atau iterable yang akan direduksi, seperti list atau tuple, initializer(opsional): nilai awal untuk memberi seed pada fungsi.

Contoh langkah demi langkah:

  •  [1, 3, 2, 7] → [4, 2, 7].
  • [4, 2, 7] → [6, 7].
  • [6, 7] → [13].

Hasil akhirnya adalah 13.

Contoh sederhana reduce()

Contoh mainan berikut menunjukkan mekanisme cara menggunakan reduce(). 

from functools import reduce

numbers = [2, 4, 6]
product = reduce(lambda x, y: x * y, numbers)  # ((2 x 4) x 6) = 8 x 6 = 48
min_value = reduce(lambda x, y: x if x < y else y, numbers) # 2

words = ['dog', 'cat', 'tree', 'pony']
str_concat = reduce(lambda x, y: x + y, words)  # "dogcattreepony"

Initializer

Tanpa initializer, reduce() menggunakan elemen pertama dari iterable sebagai nilai awalnya. Jika iterable kosong, reduce() akan melempar TypeError. Untuk membuat kode tangguh, berikan initializer untuk mendefinisikan perilaku pada masukan kosong.

from functools import reduce

words = []
# Error: reduce() of empty iterable with no initial value
str_concat = reduce(lambda x, y: x + y, words)

# Correct: use empty string initializer
str_concat = reduce(lambda x, y: x + y, words, "")

Initializer juga memberi seed hasil dengan kontainer kosong. Misalnya, Anda dapat menggabungkan kata menjadi daftar karakter datar. 

from functools import reduce

words = ['reduce', 'is', 'fun']
chars_list = reduce(lambda acc, word: acc + list(word), words, [])
print(chars_list)  # ['r', 'e', 'd', 'u', 'c', 'e', 'i', 's', 'f', 'u', 'n']

Untuk mengeksplorasi Python dan manipulasi data lebih jauh, berikut beberapa opsi yang saya rekomendasikan.

Mendefinisikan reducer

Sejauh ini, kita menggunakan fungsi lambda untuk mendefinisikan operator biner. 

Anda juga dapat menggunakan operator dari modul operator.  Modul operator berisi versi fungsi dari operator umum dan pemanggilan metode. Misalnya, alih-alih x + y, gunakan operator.add(x, y). Ini memungkinkan Anda memasukkan operator siap pakai (dan efisien) ke reduce() tanpa perlu menulis lambda.

from functools import reduce
import operator as op

numbers = [2, 4, 6]
total = reduce(op.add, numbers, 0)  # instead of reduce(lambda x,y: x + y, numbers)

Opsi ketiga adalah menulis fungsi kustom. Ini pilihan yang baik saat tidak ada operator yang sudah tersedia atau fungsinya terlalu rumit untuk lambda. 

Sebagai contoh, misalkan Anda ingin menghapus duplikasi dari sebuah list, tetapi mempertahankan urutan kemunculan pertama. Anda dapat mendefinisikan reducer yang menambahkan item ke list hanya jika item tersebut belum muncul sebelumnya.  

from functools import reduce


items = ['the', 'wild', 'wild', 'world', 'is', 'the', 'wide', 'world', 'is', 'the', 'world']


def dedup(acc, x):
    if x not in acc:  # O(n) membership test
        acc.append(x)
    return acc




unique = reduce(dedup, items, [])  # ['the', 'wild', 'world', 'is', 'wide']

Untuk ide lebih lanjut tentang menghapus duplikasi, pertimbangkan tutorial ini.

Kinerja reduce() di Python

reduce() memiliki isu kinerja.

Overhead pemanggilan fungsi

Python reduce() memanggil fungsi kita sekali untuk setiap elemen. Pada list dengan satu juta item, ini berarti satu juta pemanggilan fungsi, masing-masing membuat frame, menangani argumen, dan memperbarui reference count. Ini menambah overhead yang signifikan.

Sebaliknya, built-in seperti sum melakukan satu pemanggilan ke fungsi C dan menjalankan sejuta penjumlahan di dalam loop C. Perbedaan ini dapat membuat built-in jauh lebih cepat.

Lokalitas cache dan efisiensi CPU

Reduce juga terkendala lokalitas cache dan efisiensi CPU.  

CPU modern dapat mengeksekusi beberapa miliar instruksi per detik, tetapi akses RAM jauh lebih lambat. Untuk mengompensasi, CPU modern memiliki cache (L1, L2, L3) yang menyimpan data untuk akses cepat.

Cache ini mengeksploitasi dua pola. 

  • Lokalitas temporal: data yang baru digunakan kemungkinan akan digunakan lagi. 
  • Lokalitas spasial: data yang dekat dengan alamat yang baru digunakan kemungkinan akan segera digunakan.

Sebaliknya, setiap langkah reduce() melibatkan penelusuran pointer untuk menemukan elemen berikutnya dan pemanggilan fungsi Python, yang merusak lokalitas dan membuat CPU tersendat. Built-in dan fungsi tervektorisasi menghindari masalah ini dengan berjalan pada loop C yang rapat.

Untuk penyegar tentang cara menulis kode Python yang idiomatis dan efisien, lihat:

Alternatif untuk reduce() di Python

Built-in:

  • Kode C yang dioptimalkan. Built-in menjalankan loop mereka dalam kode C yang dioptimalkan, bukan Python. Itu menghindari overhead yang ditimbulkan reduce(). Keunggulan kecepatan ini semakin terasa pada input besar. 
  • Keterbacaan. Built-in memiliki nama deskriptif (sum, min) sehingga maksudnya jelas. Panggilan ke reduce() mengharuskan Anda membaca fungsi yang dilipat.

Loop:

  • Kinerja. Secara umum loop berjalan lebih lambat daripada built-in tetapi lebih cepat daripada reduce().
  • Keterbacaan. Seperti built-in, loop biasanya lebih mudah dibaca daripada reduce(). Panggilan ke reduce() memaksa Anda mem-parsing pernyataan fungsional, sedangkan loop lebih Pythonic.

itertools.accumulate()

Pustaka itertools di Python menyediakan kumpulan iterator berkinerja tinggi seperti count(), product(), dan combinations(). Salah satu fungsi itertools yang berguna adalah itertools.accumulate(). Seperti reduce(), ia melipat sebuah fungsi pada iterable. Namun, accumulate() menyimpan nilai perantara dari komputasi, bukan hanya hasil akhirnya. 

Sebagai contoh,

import itertools, operator
from functools import reduce

list(itertools.accumulate([1, 2, 3, 4], initial=0)) # [0, 1, 3, 6, 10]
reduce(operator.add, [1, 2, 3, 4], 0) # 10

Accumulate berguna saat Anda membutuhkan total berjalan atau nilai minimum/maksimum berjalan. Misalnya, Anda mungkin ingin mengetahui suhu maksimum dari bulan ke bulan.

Kesalahan Umum Saat Menggunakan reduce()

Saat Anda menggunakan reduce(), ingat jebakan berikut.

  • Lebih suka alternatif yang lebih sederhana seperti built-in atau loop. Simpan reduce() untuk saat Anda benar-benar membutuhkannya.
  • Tangani iterable kosong. Selalu gunakan initializer yang sesuai untuk menghindari error pada input kosong.
  • Perhatikan masalah memori. Jangan memaksakan reduce() ke situasi di mana pendekatan generator atau streaming akan lebih efisien.
  • Hindari lambda yang rumit. Gunakan fungsi dari modul operator bila memungkinkan. Lambda, khususnya dengan operasi non-asosiatif, dapat mengurangi kejelasan.
  • Utamakan kejelasan daripada kelihaian.

Praktik Terbaik dan Pedoman reduce() di Python 

Seperti alat apa pun, ada praktik terbaik untuk reduce(). Jika Anda telah memutuskan reduce() adalah alat yang tepat, berikut beberapa pedoman penggunaannya.

Rancang reducer terlebih dahulu 

  • Definisikan kontrak dalam satu kalimat. "Gabungkan kunci kamus dengan menjumlahkan hitungan per kunci."
  • Usahakan bersifat asosiatif jika memungkinkan. Ini memudahkan proses paralelisasi dan pengujian.
  • Identifikasi elemen identitas Anda dan gunakan sebagai initializer. Misalnya, untuk penjumlahan, identitasnya adalah 0. Untuk min, adalah math.inf, dan untuk set union, adalah set(). Ini membuat kode tangguh dan bebas dari TypeError.

Jaga tetap sederhana dan mudah dibaca

  • Satu operasi yang jelas. Tanpa efek samping.
  • Beri nama deskriptif pada reducer.

Dokumentasikan

  • Di docstring, catat elemen identitas dan perilaku input kosong, asumsi asosiativitas, kebijakan error.

Uji

  • Uji unit pada kasus tepi: iterable kosong, tipe campuran, nilai ekstrem.
  • Uji asosiativitas.

Pantau kinerja

  • Benchmark input kecil dan besar. Bandingkan benchmark dengan built-in dan loop.
  • Jika kecepatan penting, pertimbangkan prapemrosesan, batching, dan memindahkan perhitungan berat ke NumPy atau pandas.

Aplikasi Lanjutan dan Kasus Penggunaan Nyata untuk reduce() di Python

Melihat kekurangannya, mungkin tampak bahwa reduce() tidak memiliki nilai nyata. Sebaliknya, reduce() memiliki banyak kasus penggunaan yang bermanfaat. 

  • Memproses struktur bersarang
  • Operasi bergaya basis data
  • Pipa pemrosesan data
  • Aplikasi MapReduce

Memproses struktur bersarang

Reduce menyediakan cara yang rapi untuk menelusuri struktur data bersarang, seperti objek JSON, dengan mem-fold urutan kunci menjadi lookup berturut-turut.

import json
from functools import reduce
import operator

data = json.loads('''
{
  "user": {
    "id": "ABC123",
    "name": "Alice",
    "email": "alice@example.com",
    "profile": {
      "address": {
        "city": "San Francisco",
        "zip": "94103"
      },
      "age": 34,
      "skills": ["Python", "Data Science", "Machine Learning"]
    }
  }
}
''')

# Example lookups with reduce + operator.getitem
city = reduce(operator.getitem, ["user", "profile", "address", "city"], data)
print(city)  # "San Francisco"

user_id = reduce(operator.getitem, ["user", "id"], data)
print(user_id)  # "ABC123"

age = reduce(operator.getitem, ["user", "profile", "age"], data)
print(age)  # 34

Menggunakan reduce() masuk akal di sini. JSON-nya bersarang dalam: user → profile → address → city. Alih-alih merangkai lookup secara manual, wakili jalur sebagai list kunci. Lalu gunakan reduce(operator.getitem, path, data) untuk menelusurinya. Ini menjaga kode tetap generik, mudah dibaca, dan dapat digunakan ulang.

Pipa pemrosesan data

Reduce dapat menggerakkan pipa pemrosesan data dengan meneruskan data melalui rangkaian transformasi. Setiap fungsi menangani satu langkah, dan pipa dihasilkan dari menerapkannya secara berurutan. Berikut pipa sederhana yang mempraproses string teks sebelum dimasukkan ke model NLP. 

from functools import reduce
import re

# Define preprocessing steps
def strip_punctuation(s):
    return re.sub(r"[^\w\s]", "", s)

def to_lower(s):
    return s.lower()

def remove_stopwords(s):
    stops = {"the", "is", "a", "of"}
    return " ".join(word for word in s.split() if word not in stops)

def stem_words(s):
    # trivial "stemmer": cut off 'ing'
    return " ".join(word[:-3] if word.endswith("ing") else word for word in s.split())

pipeline = [
    strip_punctuation,
    to_lower,
    remove_stopwords,
    stem_words,
]

# Input data
text = "The quick brown fox is Jumping over a log."

# Apply pipeline with reduce
processed = reduce(lambda acc, f: f(acc), pipeline, text)
print(processed)  # quick brown fox jump over log

Penanganan error dalam aplikasi kompleks

Mari kembali ke contoh JSON bersarang. Saat ini, pemanggilan langsung ke reduce(operator.getitem, …) akan melempar KeyError atau TypeError jika sebuah kunci hilang atau jika bertemu non-dict. Untuk membuat kode lebih aman, definisikan fungsi pembantu yang membungkus operator.getitem dalam blok try/except dan mengembalikan nilai default saat terjadi error.

Berikut salah satu kemungkinan untuk fungsi pembantu.

def deep_get(data, keys, default=None):
    """Traverse nested dicts/lists safely with reduce."""
    try:
        return reduce(operator.getitem, keys, data)
    except (KeyError, IndexError, TypeError):
        return default

Sekarang, ubah contoh lookup untuk menggunakan fungsi baru kita alih-alih reduce() yang tidak dibungkus

# Example lookups
city = deep_get(data, ["user", "profile", "address", "city"], default="Unknown City")
print(city)  # "San Francisco"

user_id = deep_get(data, ["user", "id"], default="N/A")
print(user_id)  # "ABC123"

age = deep_get(data, ["user", "profile", "age"], default="N/A")
print(age)  # 34

# Example with missing key
phone = deep_get(data, ["user", "profile", "phone"], default="No phone")
print(phone)  # "No phone"

Transformasi data multi-langkah dengan map() dan filter()

Anda dapat menggabungkan reduce() dengan alat fungsional lain, seperti map() dan filter(), untuk membangun transformasi data multi-langkah. Berikut pipa prapemrosesan NLP kita sebelumnya yang ditulis secara fungsional.

from functools import reduce
import re

# Define preprocessing steps
def strip_punctuation(s):
    return re.sub(r"[^\w\s]", "", s)

def to_lower(s):
    return " ".join(map(str.lower, s.split()))

def remove_stopwords(s):
    stops = {"the", "is", "a", "of"}
    return " ".join(filter(lambda w: w not in stops, s.split()))

def stem_words(s):
    # trivial "stemmer": cut off 'ing'
    return " ".join(map(lambda w: w[:-3] if w.endswith("ing") else w, s.split()))

# Pipeline of transformations
pipeline = [
    strip_punctuation,
    to_lower,
    remove_stopwords,
    stem_words,
]

# Input data
text = "The quick brown fox is Jumping over a log."

# Apply pipeline with reduce
processed = reduce(lambda acc, f: f(acc), pipeline, text)
print(processed)  # quick brown fox jump over log

Transformasinya adalah:

  • Hapus tanda baca. "The quick brown fox is Jumping over a log." → "The quick brown fox is Jumping over a log"
  • Huruf kecil

"The quick brown fox is Jumping over a log" → "the quick brown fox is jumping over a log"

  • Hapus stop words. "the quick brown fox is jumping over a log" → "quick brown fox jumping over log"
  • Stem kata

 "quick brown fox jumping log"  → "quick brown fox jump log"

Untuk mengeksplorasi lebih lanjut gagasan pemrograman fungsional dan vektorisasi, kami merekomendasikan artikel DataCamp berikut.

Integrasi dengan Ekosistem Python Modern

Untuk menggunakan reduce() dengan baik, akan membantu jika memahami bagaimana ia cocok dalam ekosistem Python modern. Mari telusuri bagaimana posisinya bersama NumPy dan pandas, bagaimana ia menopang sistem paralel dan terdistribusi, serta bagaimana interaksinya dengan tooling modern seperti analis statis. 

numpy dan pandas

NumPy dan pandas bekerja dari kode C yang dioptimalkan, jadi jangan duplikasi fungsionalitasnya dengan reduce(). Namun, reduce() adalah pilihan yang baik untuk pipa dengan langkah-langkah dinamis. Misalnya, Anda mungkin menggabungkan banyak transformasi NumPy pada sebuah array.

from functools import reduce
import numpy as np

def standardize(x):
    return (x - x.mean()) / (x.std() + 1e-9)

def clip(x):
    return np.clip(x, 0, 1)

def log(x):
    return np.log1p(x)

x = np.array([1, 500, 40.5, 100, 250.45])
funcs = [standardize, clip, log]
y = reduce(lambda a, f: f(a), funcs, x)  # x is ndarray

Kerangka komputasi paralel dan terdistribusi

Reduce adalah inti dari kerangka komputasi paralel dan terdistribusi. Sistem-sistem ini bekerja dengan membagi dataset menjadi partisi, memproses partisi tersebut secara paralel, lalu menggabungkan hasil parsial menjadi satu jawaban. Langkah "combine" adalah reduksi.

Agar reduksi berjalan dengan benar di seluruh klaster, pastikan kondisi berikut terpenuhi.

  • Asosiativitas. Operasi harus memberikan hasil yang sama terlepas dari pengelompokan. Ini memungkinkan hasil parsial digabungkan dalam urutan apa pun di seluruh jaringan.
  • Elemen identitas. Operasi harus memiliki initializer yang tidak memengaruhi hasil akhir. Ini memastikan kebenaran saat partisi kosong atau berukuran tidak merata. 

Jika properti ini tidak terpenuhi, reduksi menjadi lambat (karena tidak dapat diparalelkan dengan aman) atau tidak benar (karena hasil bergantung pada urutan evaluasi).

Proses ini membutuhkan operasi yang asosiatif dan identitas yang jelas. Jika tidak, Anda mendapatkan kode yang lambat atau hasil yang salah.

Alat analisis statis

Analyzer statis (seperti mypy, Pyright, ruff, atau bandit) adalah alat yang memeriksa kode tanpa mengeksekusinya. Alat ini menangkap bug, menegakkan aturan gaya, dan memeriksa kebenaran tipe.

Analyzer statis kesulitan dengan reduce(). Dalam proses folding, tipe akumulator bisa berbeda dari tipe elemen, dan inferensi tipe menjadi berantakan. 

Pertimbangkan kode berikut.

from functools import reduce

def add_chars(acc, word):
    acc.extend(word)   # extend adds each character of the string
    return acc

chars = reduce(add_chars, ["hi", "ok"], [])
print(chars)  # ['h', 'i', 'o', 'k']

Meskipun kode ini berjalan baik, analyzer statis mungkin mengeluhkan beberapa hal.

  • Tipe elemen dari initializer [] ambigu. 
  • Analyzer mungkin mengasumsikan tipe akumulator dan elemen harus cocok.

Untuk membuat kode lebih jelas bagi manusia dan analyzer, tambahkan type hint.

from functools import reduce
from typing import List

def add_chars(acc: List[str], word: str) -> List[str]:
    acc.extend(word)   # extend adds each character of the string
    return acc

chars: List[str] = reduce(add_chars, ["hi", "ok"], [])
print(chars)  # ['h', 'i', 'o', 'k']

Sekarang reducer secara eksplisit menunjukkan

  • Akumulator adalah List[str].
  • Setiap elemen adalah str.
  • Tipe nilai kembalian adalah list[str].

Dengan hint ini, analyzer statis dapat memeriksa kode secara ketat. 

Kesimpulan

Reduce berasal dari pemrograman fungsional, di mana melipat koleksi menjadi satu hasil adalah gagasan inti. Meskipun tidak lagi menjadi alat kelas satu di Python, ia tetap memiliki tempatnya. Saat Anda membutuhkan pipa yang fleksibel, fold kustom, atau operasi yang tidak secara mulus dipetakan ke fungsi yang ada, reduce() adalah alat yang kuat. Jika digunakan dengan hati-hati, ia terintegrasi dengan baik dengan ekosistem Python yang lebih luas dan tetap menjadi alat yang praktis dalam situasi yang tepat.

Beberapa tautan Python terkait yang mungkin berguna.

Python reduce() FAQs

Apa yang dilakukan reduce()?

Fungsi ini berulang kali menerapkan fungsi dua argumen pada sebuah iterable untuk mereduksinya menjadi satu hasil.

Di mana reduce() didefinisikan?

Sebelum versi 3, ini adalah fungsi built-in. Sejak itu, fungsi ini berada di modul functools.

Fungsi seperti apa yang sebaiknya saya berikan ke reduce()?

Fungsi yang sederhana, asosiatif, dan terdokumentasi dengan baik. Hindari efek samping dan logika non-asosiatif.

Bagaimana perbandingannya dengan itertools.accumulate()?

reduce() hanya mengembalikan hasil akhir, accumulate() menghasilkan semua hasil perantara.

Kapan saya harus menggunakan initializer?

Gunakan initializer ketika iterable mungkin kosong.

Topik
Python
Data Science

Kursus Python Teratas

Kursus

Menulis Kode Python yang Efisien

4 jam
156K
Pelajari cara menulis kode efisien yang berjalan cepat dan mengalokasikan sumber daya dengan terampil untuk menghindari overhead yang tidak perlu.
Lihat DetailRight Arrow
Mulai Kursus
Lihat SelengkapnyaRight Arrow
Terkait

blogs

Tutorial Korelasi di R

Dapatkan pengenalan dasar-dasar korelasi di R: pelajari lebih lanjut tentang koefisien korelasi, matriks korelasi, plotting korelasi, dan sebagainya.
David Woods's photo

David Woods

13 mnt

blogs

Spaghetti Plot dan Jalur Badai

Temukan alasan mengapa Anda sebaiknya (tidak) menggunakan spaghetti plot untuk menyampaikan ketidakpastian jalur prediksi badai serta dampaknya terhadap interpretasi.
Hugo Bowne-Anderson's photo

Hugo Bowne-Anderson

13 mnt

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

Kuasai pertanyaan wawancara basis data, dari konsep SQL dasar hingga skenario desain sistem tingkat lanjut. Panduan mendalam ini mencakup semua yang Anda perlukan untuk sukses di wawancara DBMS dan meraih peran berikutnya.
Dario Radečić's photo

Dario Radečić

15 mnt

blogs

12 Alternatif ChatGPT Terbaik yang Bisa Anda Coba pada 2026

Artikel ini menyajikan daftar alternatif ChatGPT yang akan meningkatkan produktivitas Anda.
Javier Canales Luna's photo

Javier Canales Luna

14 mnt

Lihat SelengkapnyaLihat Selengkapnya