Python & AI Tutorials Logo
Pemrograman Python

22. Mengorganisasi Kode dengan Modul dan Paket

Seiring program Python kamu makin besar, menyimpan semua kode dalam satu file jadi tidak praktis. Kamu akan ingin mengorganisasi fungsi, kelas, dan variabel yang saling terkait ke dalam file-file terpisah yang bisa digunakan ulang di berbagai program. Sistem modul (module) dan paket (package) Python menyediakan kemampuan ini—cara untuk mengorganisasi, membagikan, dan menggunakan ulang kode secara efektif.

Di bab ini, kita akan membahas cara kerja sistem import Python, cara membuat dan menggunakan modul buatan sendiri, serta cara mengorganisasi banyak modul menjadi paket. Kita juga akan membahas variabel khusus __name__ yang memungkinkan kamu menulis file yang bisa berfungsi sebagai modul yang dapat di-import sekaligus sebagai skrip mandiri.

22.1) Apa Itu Modul dan Bagaimana import Bekerja

Memahami Modul

Sebuah modul (module) pada dasarnya adalah file Python yang berisi definisi dan statement. File .py apa pun yang kamu buat adalah sebuah modul. Saat kamu menulis sebuah fungsi dalam file bernama calculator.py, file tersebut menjadi modul bernama calculator yang bisa digunakan oleh file Python lainnya.

Modul memiliki beberapa tujuan penting:

  • Dapat Digunakan Ulang (Code Reusability): Tulis fungsi sekali dan gunakan di banyak program
  • Organisasi: Mengelompokkan fungsionalitas yang terkait
  • Manajemen Namespace (Namespace Management): Memisahkan nama agar tidak bentrok
  • Kemudahan Perawatan (Maintainability): File yang lebih kecil dan fokus lebih mudah dipahami dan dimodifikasi

Mari buat modul sederhana untuk melihat cara kerjanya. Buat file bernama greetings.py:

python
# greetings.py
def say_hello(name):
    """Return a friendly greeting."""
    return f"Hello, {name}!"
 
def say_goodbye(name):
    """Return a farewell message."""
    return f"Goodbye, {name}. See you soon!"
 
# Variabel tingkat-modul
default_greeting = "Welcome"

File ini sekarang adalah sebuah modul. Ia berisi dua fungsi dan satu variabel yang bisa digunakan oleh file Python lain.

Statement import

Untuk menggunakan kode dari sebuah modul, kamu import modul tersebut. Statement import memberi tahu Python untuk memuat modul dan membuat isinya tersedia. Buat file lain di direktori yang sama bernama main.py:

python
# main.py
import greetings
 
message = greetings.say_hello("Alice")
print(message)  # Output: Hello, Alice!
 
farewell = greetings.say_goodbye("Bob")
print(farewell)  # Output: Goodbye, Bob. See you soon!
 
print(greetings.default_greeting)  # Output: Welcome

Saat kamu menjalankan main.py, Python mengeksekusi statement import greetings. Berikut yang terjadi di balik layar:

Tidak

Ya

import greetings

Apakah greetings
sudah di-import?

Cari greetings.py

Eksekusi greetings.py
dari atas ke bawah

Buat objek modul
bernama 'greetings'

Simpan fungsi dan variabel
sebagai atribut

Buat 'greetings' tersedia
di namespace saat ini

Gunakan objek modul
yang sudah ada

Penting: Python hanya mengeksekusi kode modul pada saat pertama kali di-import dalam sebuah program. Import berikutnya dalam program yang sama akan menggunakan ulang modul yang sudah dimuat. Ini mencegah eksekusi ganda dan menghemat waktu.

Mengakses Isi Modul

Setelah meng-import modul, kamu mengakses isinya dengan dot notation (notasi titik): module_name.item_name. Ini mirip seperti cara kita mengakses method string seperti text.upper() atau method list seperti numbers.append(), seperti yang kita pelajari di Bab 5 dan 14.

python
import greetings
 
# Akses fungsi
result = greetings.say_hello("Charlie")
 
# Akses variabel
greeting = greetings.default_greeting
 
# Kamu bahkan bisa mengecek apa saja yang ada di dalam modul
print(dir(greetings))  # Menampilkan semua nama yang didefinisikan di modul

Notasi titik memperjelas dari mana setiap nama berasal. Saat kamu melihat greetings.say_hello(), kamu langsung tahu fungsi ini berasal dari modul greetings.

Jalur Pencarian Modul

Saat kamu menulis import greetings, bagaimana Python menemukan greetings.py? Python mencari modul dalam urutan tertentu:

  1. Direktori Saat Ini: Direktori yang berisi skrip yang sedang kamu jalankan
  2. PYTHONPATH: Direktori yang tercantum di environment variable PYTHONPATH (jika disetel)
  3. Standard Library (Pustaka Standar): Direktori modul bawaan Python
  4. Site-Packages: Paket pihak ketiga yang diinstal dengan pip

Kamu bisa melihat jalur pencarian Python dengan memeriksa sys.path:

python
import sys
 
for path in sys.path:
    print(path)

Output (contoh - path kamu akan berbeda tergantung sistem dan instalasi Python):

/home/user/projects/myproject
/usr/lib/python3.11
/usr/lib/python3.11/lib-dynload
/usr/local/lib/python3.11/site-packages

Path pertama pada output adalah current working directory. Python mencari direktori ini terlebih dahulu, jadi ia bisa menemukan modul di direktori yang sama.

Nama Modul dan Nama File

Nama modul adalah nama file tanpa ekstensi .py. Jika file kamu adalah string_utils.py, nama modulnya adalah string_utils. Nama modul harus mengikuti aturan identifier Python (seperti yang kita pelajari di Bab 3):

  • Diawali dengan huruf atau underscore
  • Hanya berisi huruf, digit, dan underscore
  • Tidak boleh berupa keyword Python
python
# Nama modul yang valid (dan nama file)
import data_processor      # data_processor.py
import user_auth          # user_auth.py
import _internal_helpers  # _internal_helpers.py
 
# Tidak valid - akan menyebabkan error
# import 2d_graphics       # Can't start with digit
# import my-module         # Hyphens not allowed
# import class             # 'class' is a keyword

Kesalahan Umum: Menimpa (Shadowing) Modul Standard Library

Hati-hati agar tidak memberi nama modul kamu sama dengan modul standard library. Jika kamu membuat file bernama random.py di direktori proyekmu, Python akan meng-import file milikmu alih-alih modul random dari standard library, yang bisa menyebabkan error membingungkan:

python
# File kamu: random.py
def my_function():
    return 42
 
# File lain di proyek kamu
import random
print(random.randint(1, 6))  # ERROR! Your random.py doesn't have randint()

Untuk menghindarinya, cek apakah sebuah nama sudah digunakan oleh standard library sebelum membuat modul dengan nama tersebut. Kamu bisa mengecek dengan mencoba meng-import-nya di Python interactive shell. Jika bisa di-import tanpa error, nama itu sudah dipakai.

Apa yang Terjadi Saat Import

Mari kita lihat apa yang benar-benar terjadi saat kamu meng-import modul. Buat file bernama demo_module.py:

python
# demo_module.py
print("Module is being loaded!")
 
def greet():
    print("Hello from demo_module")
 
print("Module loading complete!")

Sekarang import:

python
# test_import.py
print("Before import")
import demo_module
print("After import")
 
demo_module.greet()

Output:

Before import
Module is being loaded!
Module loading complete!
After import
Hello from demo_module

Perhatikan bahwa statement print() di demo_module.py dieksekusi saat import. Ini menunjukkan bahwa meng-import modul menjalankan semua kode tingkat-atasnya. Definisi fungsi disimpan untuk digunakan nanti, tetapi kode apa pun di luar fungsi langsung dieksekusi.

Jika kamu meng-import modul yang sama lagi dalam program yang sama, pesan pemuatan tidak akan muncul lagi:

python
import demo_module  # First import - executes module code
import demo_module  # Second import - uses cached module
import demo_module  # Third import - still uses cached module

Output:

Module is being loaded!
Module loading complete!

Kode modul hanya berjalan sekali, tidak peduli berapa kali kamu meng-import-nya.

22.2) Berbagai Cara Import: import, from, dan as

Python menyediakan beberapa cara untuk meng-import modul dan isinya. Setiap pendekatan punya implikasi berbeda pada cara kamu mengakses nama yang di-import dan bagaimana pengaruhnya terhadap namespace kamu.

Statement import Dasar

Statement import dasar yang sudah kita lihat akan memuat seluruh modul:

python
import math
 
result = math.sqrt(16)
print(result)  # Output: 4.0
 
pi_value = math.pi
print(pi_value)  # Output: 3.141592653589793

Dengan pendekatan ini, kamu selalu memakai nama modul sebagai prefix. Ini membuat kode sangat jelas—kamu selalu bisa tahu sebuah nama berasal dari mana.

Meng-import Nama Tertentu dengan from

Kadang kamu hanya butuh satu atau dua item dari modul. Statement from memungkinkan kamu meng-import nama tertentu langsung ke namespace kamu:

python
from math import sqrt, pi
 
result = sqrt(25)  # No 'math.' prefix needed
print(result)  # Output: 5.0
 
print(pi)  # Output: 3.141592653589793

Sekarang kamu bisa memakai sqrt dan pi langsung tanpa prefix math.. Ini praktis saat kamu sering memakai nama-nama ini.

Mari lihat contoh lain dengan modul greetings kita:

python
# Menggunakan from import
from greetings import say_hello
 
message = say_hello("Diana")  # Akses langsung
print(message)  # Output: Hello, Diana!
 
# Namun, say_goodbye tidak tersedia karena kita tidak meng-import-nya
# say_goodbye("Diana")  # NameError: name 'say_goodbye' is not defined

Kamu bisa meng-import beberapa nama dalam satu statement:

python
from greetings import say_hello, say_goodbye, default_greeting
 
print(say_hello("Eve"))      # Output: Hello, Eve!
print(say_goodbye("Frank"))  # Output: Goodbye, Frank!
print(default_greeting)      # Output: Welcome

Wildcard Import (dan Mengapa Sebaiknya Dihindari)

Python memungkinkan meng-import semuanya dari modul menggunakan *:

python
from math import *
 
print(sqrt(9))   # Output: 3.0
print(cos(0))    # Output: 1.0
print(pi)        # Output: 3.141592653589793

Ini meng-import semua nama publik dari modul (nama yang tidak diawali underscore). Meski terlihat praktis, umumnya ini dianggap praktik yang buruk karena:

  1. Pencemaran Namespace (Namespace Pollution): Kamu tidak tahu persis nama apa saja yang di-import
  2. Konflik Nama (Name Conflicts): Nama yang di-import bisa menimpa variabel kamu sendiri
  3. Keterbacaan (Readability): Pembaca kode tidak bisa tahu nama itu berasal dari mana
python
# Contoh yang bermasalah
from math import *
 
# Nanti di kode kamu...
def sqrt(x):
    """Your own square root function."""
    return x ** 0.5
 
# sqrt yang mana yang kamu gunakan? Milikmu atau milik math?
result = sqrt(16)  # Membingungkan!

Praktik Terbaik (Best Practice): Import nama tertentu atau gunakan statement import dasar. Hindari from module import * kecuali dalam sesi interaktif saat kamu bereksperimen.

Mengganti Nama Import dengan as

Kadang nama modul atau fungsi panjang, atau kamu ingin menghindari konflik nama. Keyword as memungkinkan kamu membuat alias:

python
import math as m
 
result = m.sqrt(36)
print(result)  # Output: 6.0

Ini sangat berguna untuk modul dengan nama panjang atau saat mengikuti konvensi umum:

python
import datetime as dt
 
today = dt.date.today()
print(today)  # Output: 2025-12-19 (or current date)

Kamu juga bisa mengganti nama untuk import tertentu:

python
from math import sqrt as square_root
 
result = square_root(49)
print(result)  # Output: 7.0

Ini membantu saat ada konflik nama:

python
from math import sqrt as math_sqrt
 
def sqrt(x):
    """Custom square root with input validation."""
    if x < 0:
        return None
    return math_sqrt(x)
 
print(sqrt(25))   # Output: 5.0 (your function)
print(sqrt(-4))   # Output: None (your function)

Menggabungkan Gaya Import

Kamu bisa mencampur gaya import yang berbeda dalam file yang sama:

python
import math
from datetime import date, time
from random import randint as random_int
 
# Gunakan math dengan prefix
radius = 5
area = math.pi * radius ** 2
 
# Gunakan date dan time secara langsung
today = date.today()
current_time = time(14, 30)
 
# Gunakan fungsi yang diganti nama
dice_roll = random_int(1, 6)

Memilih Gaya Import yang Tepat

Berikut panduan keputusan:

Gunakan import module ketika:

  • Kamu butuh banyak item dari modul
  • Kamu ingin kejelasan maksimal tentang dari mana nama berasal
  • Nama modul pendek dan jelas

Gunakan from module import name ketika:

  • Kamu hanya butuh satu atau dua item tertentu
  • Nama-namanya khas dan kecil kemungkinan bentrok
  • Kamu akan sering memakai nama-nama itu

Gunakan import module as alias ketika:

  • Nama modul sangat panjang
  • Mengikuti konvensi umum (seperti import numpy as np)
  • Kamu perlu menghindari konflik dengan modul lain

Hindari from module import * pada kode production:

  • Gunakan hanya untuk eksperimen cepat di interactive shell
  • Jangan pernah menggunakannya di modul yang akan di-import orang lain

Mari lihat contoh lengkap yang menunjukkan praktik import yang baik:

python
# data_processor.py
import math
from statistics import mean, median
from datetime import datetime as dt
 
def calculate_statistics(numbers):
    """Calculate various statistics for a list of numbers."""
    if not numbers:
        return None
    
    avg = mean(numbers)
    mid = median(numbers)
    std_dev = math.sqrt(sum((x - avg) ** 2 for x in numbers) / len(numbers))
    
    return {
        'mean': avg,
        'median': mid,
        'std_dev': std_dev,
        'timestamp': dt.now()
    }
 
# Uji fungsi
data = [10, 20, 30, 40, 50]
stats = calculate_statistics(data)
print(f"Mean: {stats['mean']}")      # Output: Mean: 30.0
print(f"Median: {stats['median']}")  # Output: Median: 30
print(f"Std Dev: {stats['std_dev']:.2f}")  # Output: Std Dev: 14.14

Contoh ini menunjukkan:

  • import math untuk modul penuh (kita mungkin memakai fungsi math lain nanti)
  • from statistics import mean, median untuk fungsi spesifik yang sering kita gunakan
  • from datetime import datetime as dt untuk modul yang umum diberi alias

22.3) Gambaran Umum Modul-Modul Standard Library Python yang Sering Digunakan

Python hadir dengan standard library (pustaka standar Python) yang kaya—kumpulan modul yang menyediakan solusi untuk tugas pemrograman umum. Modul-modul ini selalu tersedia; kamu tidak perlu menginstal apa pun tambahan. Memahami apa yang tersedia di standard library membantu kamu menghindari "menciptakan ulang roda."

Modul math

Modul math menyediakan fungsi matematika di luar aritmetika dasar:

python
import math
 
# Fungsi trigonometri
angle_rad = math.radians(45)  # Ubah derajat ke radian
print(math.sin(angle_rad))    # Output: 0.7071067811865476
print(math.cos(angle_rad))    # Output: 0.7071067811865475
 
# Pembulatan dan nilai absolut
print(math.ceil(4.2))   # Output: 5 (bulatkan ke atas)
print(math.floor(4.8))  # Output: 4 (bulatkan ke bawah)
print(math.fabs(-7.5))  # Output: 7.5 (nilai absolut sebagai float)
 
# Eksponensial dan logaritmik
print(math.exp(2))      # Output: 7.38905609893065 (e^2)
print(math.log(100))    # Output: 4.605170185988092 (natural log)
print(math.log10(100))  # Output: 2.0 (base-10 log)
 
# Konstanta
print(math.pi)  # Output: 3.141592653589793
print(math.e)   # Output: 2.718281828459045

Seperti yang kita pelajari di Bab 4, modul math penting untuk operasi matematika tingkat lanjut.

Modul random

Modul random menghasilkan bilangan pseudo-acak dan membuat pilihan acak:

python
import random
 
# Bilangan bulat acak
dice = random.randint(1, 6)  # Random integer from 1 to 6 (inclusive)
print(f"Dice roll: {dice}")
 
# Float acak
probability = random.random()  # Random float from 0.0 to 1.0
print(f"Probability: {probability:.4f}")
 
# Pilihan acak dari sebuah sequence
colors = ['red', 'blue', 'green', 'yellow']
chosen_color = random.choice(colors)
print(f"Chosen color: {chosen_color}")
 
# Acak urutan list secara in-place
deck = ['A', 'K', 'Q', 'J', '10']
random.shuffle(deck)
print(f"Shuffled deck: {deck}")
 
# Sampel acak tanpa penggantian
lottery_numbers = random.sample(range(1, 50), 6)
print(f"Lottery numbers: {sorted(lottery_numbers)}")

Output (contoh - akan bervariasi karena acak):

Dice roll: 4
Probability: 0.7382
Chosen color: green
Shuffled deck: ['Q', 'A', '10', 'K', 'J']
Lottery numbers: [7, 15, 23, 31, 38, 42]

Modul datetime

Modul datetime menangani tanggal dan waktu:

python
from datetime import date, time, datetime, timedelta
 
# Tanggal dan waktu saat ini
today = date.today()
now = datetime.now()
print(f"Today: {today}")  # Output: Today: 2025-12-19
print(f"Now: {now}")      # Output: Now: 2025-12-19 14:30:45.123456
 
# Membuat tanggal dan waktu tertentu
birthday = date(1990, 5, 15)
meeting_time = time(14, 30)
appointment = datetime(2025, 12, 25, 10, 0)
 
print(f"Birthday: {birthday}")          # Output: Birthday: 1990-05-15
print(f"Meeting: {meeting_time}")       # Output: Meeting: 14:30:00
print(f"Appointment: {appointment}")    # Output: Appointment: 2025-12-25 10:00:00
 
# Aritmetika tanggal dengan timedelta
tomorrow = today + timedelta(days=1)
next_week = today + timedelta(weeks=1)
print(f"Tomorrow: {tomorrow}")    # Output: Tomorrow: 2025-12-20
print(f"Next week: {next_week}")  # Output: Next week: 2025-12-26
 
# Mengambil komponen
print(f"Year: {today.year}")      # Output: Year: 2025
print(f"Month: {today.month}")    # Output: Month: 12
print(f"Day: {today.day}")        # Output: Day: 19

Modul os

Modul os menyediakan fungsionalitas sistem operasi. Kita akan membahas ini secara detail di Bab 26, tetapi berikut pratinjau:

python
import os
 
# Direktori kerja saat ini
current_dir = os.getcwd()
print(f"Current directory: {current_dir}")
 
# Daftar file dalam sebuah direktori
files = os.listdir('.')
print(f"Files: {files[:3]}")  # Tampilkan 3 file pertama
 
# Cek apakah sebuah path ada
exists = os.path.exists('myfile.txt')
print(f"File exists: {exists}")
 
# Gabungkan komponen path (berfungsi lintas sistem operasi)
file_path = os.path.join('data', 'users', 'profile.txt')
print(f"Path: {file_path}")  # Output: data/users/profile.txt (or data\users\profile.txt on Windows)

Modul sys

Modul sys menyediakan parameter dan fungsi yang spesifik terhadap sistem:

python
import sys
 
# Informasi versi Python
print(f"Python version: {sys.version}")
print(f"Version info: {sys.version_info}")
 
# Informasi platform
print(f"Platform: {sys.platform}")  # Output: linux, darwin, win32, etc.
 
# Ukuran integer maksimum
print(f"Max int: {sys.maxsize}")

Modul statistics

Modul statistics menyediakan fungsi untuk perhitungan statistik:

python
import statistics
 
grades = [85, 92, 78, 90, 88, 95, 82]
 
# Ukuran pemusatan
avg = statistics.mean(grades)
mid = statistics.median(grades)
mode_val = statistics.mode([1, 2, 2, 3, 3, 3, 4])
 
print(f"Mean: {avg}")      # Output: Mean: 87.14285714285714
print(f"Median: {mid}")    # Output: Median: 88
print(f"Mode: {mode_val}") # Output: Mode: 3
 
# Sebaran
std_dev = statistics.stdev(grades)
variance = statistics.variance(grades)
 
print(f"Standard deviation: {std_dev:.2f}")  # Output: Standard deviation: 5.90
print(f"Variance: {variance:.2f}")           # Output: Variance: 34.81

Modul collections

Modul collections menyediakan tipe container khusus. Kita akan membahas ini lebih jauh di Bab 39, tetapi berikut sekilas:

python
from collections import Counter, defaultdict
 
# Counter - menghitung kemunculan
text = "hello world"
letter_counts = Counter(text)
print(letter_counts)  # Output: Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
print(letter_counts['l'])  # Output: 3
 
# defaultdict - dictionary dengan nilai default
word_lists = defaultdict(list)
word_lists['fruits'].append('apple')
word_lists['fruits'].append('banana')
word_lists['vegetables'].append('carrot')
print(dict(word_lists))  # Output: {'fruits': ['apple', 'banana'], 'vegetables': ['carrot']}

Menemukan Lebih Banyak Modul Standard Library

Standard library Python berisi lebih dari 200 modul. Kamu bisa mengeksplorasinya dengan beberapa cara:

python
# Lihat semua modul yang tersedia (ini butuh sedikit waktu)
help('modules')
 
# Dapatkan bantuan untuk modul tertentu
import math
help(math)
 
# Lihat apa saja yang ada di dalam sebuah modul
import random
print(dir(random))

Dokumentasi Python (https://docs.python.org/3/library/) menyediakan informasi lengkap tentang setiap modul standard library. Seiring kamu makin berpengalaman, kamu akan menemukan modul mana yang paling berguna untuk pekerjaanmu.

22.4) Membuat dan Menggunakan Modul Buatan Sendiri

Membuat modul sendiri itu mudah—file Python apa pun bisa menjadi modul. Kuncinya adalah mengorganisasi kode kamu dengan bijak agar modul tetap fokus, dapat digunakan ulang, dan mudah dipahami.

Membuat Modul Sederhana

Mari buat modul untuk mengolah nilai siswa. Buat file bernama grade_calculator.py:

python
# grade_calculator.py
"""Module for calculating and analyzing student grades."""
 
def calculate_average(grades):
    """Calculate the average of a list of grades."""
    if not grades:
        return 0
    return sum(grades) / len(grades)
 
def get_letter_grade(numeric_grade):
    """Convert a numeric grade to a letter grade."""
    if numeric_grade >= 90:
        return 'A'
    elif numeric_grade >= 80:
        return 'B'
    elif numeric_grade >= 70:
        return 'C'
    elif numeric_grade >= 60:
        return 'D'
    else:
        return 'F'
 
def find_highest(grades):
    """Find the highest grade in a list."""
    if not grades:
        return None
    return max(grades)
 
def find_lowest(grades):
    """Find the lowest grade in a list."""
    if not grades:
        return None
    return min(grades)
 
# Konstanta tingkat-modul
PASSING_GRADE = 60
HONOR_ROLL_THRESHOLD = 90

Sekarang buat file lain untuk menggunakan modul ini:

python
# student_report.py
import grade_calculator
 
# Nilai ujian siswa
test_scores = [85, 92, 78, 88, 95]
 
# Hitung statistik
average = grade_calculator.calculate_average(test_scores)
letter = grade_calculator.get_letter_grade(average)
highest = grade_calculator.find_highest(test_scores)
lowest = grade_calculator.find_lowest(test_scores)
 
# Buat laporan
print("Student Grade Report")
print("=" * 40)
print(f"Test Scores: {test_scores}")
print(f"Average: {average:.1f}")
print(f"Letter Grade: {letter}")
print(f"Highest Score: {highest}")
print(f"Lowest Score: {lowest}")
 
# Cek honor roll
if average >= grade_calculator.HONOR_ROLL_THRESHOLD:
    print("Status: HONOR ROLL!")
elif average >= grade_calculator.PASSING_GRADE:
    print("Status: Passing")
else:
    print("Status: Needs Improvement")

Output:

Student Grade Report
========================================
Test Scores: [85, 92, 78, 88, 95]
Average: 87.6
Letter Grade: B
Highest Score: 95
Lowest Score: 78
Status: Passing

Dokumentasi Modul

Perhatikan docstring di bagian atas grade_calculator.py. Docstring tingkat-modul ini menjelaskan apa yang dilakukan modul. Ini akan muncul saat seseorang memakai help():

python
import grade_calculator
help(grade_calculator)

Ini menampilkan dokumentasi modul, termasuk docstring modul dan semua docstring fungsi. Dokumentasi yang baik membuat modul kamu lebih mudah digunakan.

Variabel dan Konstanta Tingkat-Modul

Modul bisa berisi variabel yang dibagikan ke semua penggunaan modul. Ini sering dipakai untuk konfigurasi atau konstanta:

python
# config.py
"""Application configuration settings."""
 
# Pengaturan database
DB_HOST = "localhost"
DB_PORT = 5432
DB_NAME = "myapp"
 
# Pengaturan aplikasi
MAX_LOGIN_ATTEMPTS = 3
SESSION_TIMEOUT = 1800  # seconds
DEBUG_MODE = False
 
# Path file
DATA_DIR = "/var/data"
LOG_DIR = "/var/log"
 
# Feature flags
ENABLE_CACHING = True
ENABLE_LOGGING = True

Menggunakan konfigurasi dari sebuah modul:

python
# app.py
import config
 
def connect_database():
    """Connect to the database using config settings."""
    print(f"Connecting to {config.DB_HOST}:{config.DB_PORT}")
    print(f"Database: {config.DB_NAME}")
    
    if config.DEBUG_MODE:
        print("DEBUG: Connection details logged")
 
def check_login_attempts(attempts):
    """Check if login attempts exceed the limit."""
    if attempts >= config.MAX_LOGIN_ATTEMPTS:
        print(f"Too many attempts! Maximum is {config.MAX_LOGIN_ATTEMPTS}")
        return False
    return True
 
connect_database()
print(check_login_attempts(2))  # Output: True
print(check_login_attempts(4))  # Output: Too many attempts! Maximum is 3

Output:

Connecting to localhost:5432
Database: myapp
True
Too many attempts! Maximum is 3

Penting: Variabel tingkat-modul dibagikan ke semua import. Jika kamu memodifikasi variabel modul, perubahan tersebut memengaruhi semua kode yang memakai modul itu:

python
# file1.py
import config
config.DEBUG_MODE = True
print(f"File1 - Debug mode: {config.DEBUG_MODE}")
 
# file2.py
import config
print(f"File2 - Debug mode: {config.DEBUG_MODE}")  # Akan menjadi True!

Perilaku ini bisa berguna tetapi juga bisa mengejutkan. Berhati-hatilah saat memodifikasi variabel tingkat-modul.

Nama Private dalam Modul

Secara konvensi, nama yang diawali underscore dianggap private atau internal untuk modul tersebut:

python
# user_manager.py
"""Module for managing user accounts."""
 
# Fungsi bantuan private
def _validate_email(email):
    """Internal function to validate email format."""
    return '@' in email and '.' in email
 
# Fungsi publik
def create_user(username, email):
    """Create a new user account."""
    if not _validate_email(email):
        return None
    
    user = {
        'username': username,
        'email': email,
        'active': True
    }
    return user
 
# Konstanta private
_MAX_USERNAME_LENGTH = 20
 
# Konstanta publik
MIN_PASSWORD_LENGTH = 8

Saat kamu memakai from user_manager import *, nama private (yang diawali underscore) tidak akan di-import. Namun, kamu masih bisa mengaksesnya secara eksplisit jika diperlukan:

python
import user_manager
 
# Fungsi publik - memang ditujukan untuk digunakan
user = user_manager.create_user("alice", "alice@example.com")
 
# Fungsi private - bisa diakses tetapi sebaiknya jangan bergantung padanya
# (bisa berubah di versi mendatang)
is_valid = user_manager._validate_email("test@test.com")

Prefix underscore adalah sinyal untuk programmer lain: "Ini adalah detail implementasi. Jangan bergantung bahwa ini akan tetap sama."

22.5) Memahami Paket dan __init__.py

Saat proyek membesar, kamu akan ingin mengorganisasi beberapa modul terkait ke dalam sebuah paket (package). Paket adalah sebuah direktori yang berisi modul Python dan file khusus __init__.py.

Apa Itu Paket?

Sebuah paket (package) adalah cara untuk mengorganisasi beberapa modul dalam struktur hierarkis. Anggap saja sebagai folder yang berisi file Python, di mana folder itu sendiri bisa di-import.

Berikut struktur paket sederhana:

myproject/
    main.py
    utilities/
        __init__.py
        text.py
        math.py
        file.py

Dalam struktur ini, utilities adalah paket yang berisi tiga modul: text, math, dan file. File __init__.py (yang bisa kosong) memberi tahu Python bahwa utilities adalah sebuah paket.

Membuat Paket Sederhana

Mari buat paket untuk pemrosesan data. Pertama, buat struktur direktori berikut:

data_tools/
    __init__.py
    validators.py
    formatters.py

Buat validators.py:

python
# data_tools/validators.py
"""Data validation functions."""
 
def is_valid_email(email):
    """Check if email has basic valid format."""
    return '@' in email and '.' in email.split('@')[1]
 
def is_valid_phone(phone):
    """Check if phone number has valid format (simple check)."""
    digits = ''.join(c for c in phone if c.isdigit())
    return len(digits) == 10
 
def is_positive_number(value):
    """Check if value is a positive number."""
    try:
        return float(value) > 0
    except (ValueError, TypeError):
        return False

Buat formatters.py:

python
# data_tools/formatters.py
"""Data formatting functions."""
 
def format_phone(phone):
    """Format phone number as (XXX) XXX-XXXX."""
    digits = ''.join(c for c in phone if c.isdigit())
    if len(digits) != 10:
        return phone
    return f"({digits[:3]}) {digits[3:6]}-{digits[6:]}"
 
def format_currency(amount):
    """Format number as currency."""
    return f"${amount:,.2f}"
 
def format_percentage(value, decimals=1):
    """Format number as percentage."""
    return f"{value * 100:.{decimals}f}%"

Buat __init__.py kosong:

python
# data_tools/__init__.py
"""Data processing tools package."""

Meng-import dari Paket

Sekarang kamu bisa meng-import dari paket dengan beberapa cara:

python
# Metode 1: Import modul dari paket
import data_tools.validators
 
email = "user@example.com"
is_valid = data_tools.validators.is_valid_email(email)
print(f"Email valid: {is_valid}")  # Output: Email valid: True
 
# Metode 2: Import modul tertentu dengan from
from data_tools import formatters
 
phone = "1234567890"
formatted = formatters.format_phone(phone)
print(f"Formatted phone: {formatted}")  # Output: Formatted phone: (123) 456-7890
 
# Metode 3: Import fungsi tertentu
from data_tools.validators import is_valid_phone
from data_tools.formatters import format_currency
 
print(is_valid_phone("555-1234"))  # Output: False (not 10 digits)
print(format_currency(1234.56))    # Output: $1,234.56

File __init__.py

File __init__.py punya dua tujuan:

  1. Menandai direktori sebagai paket: Python mengenali direktori dengan __init__.py sebagai paket
  2. Kode inisialisasi paket: Kode di __init__.py berjalan saat paket pertama kali di-import

File __init__.py bisa kosong, tetapi juga bisa berisi kode untuk memudahkan penggunaan paket:

python
# data_tools/__init__.py
"""Data processing tools package."""
 
# Import fungsi yang sering digunakan ke namespace paket
from data_tools.validators import is_valid_email, is_valid_phone
from data_tools.formatters import format_phone, format_currency
 
# Versi paket
__version__ = '1.0.0'
 
# Konstanta tingkat-paket
DEFAULT_CURRENCY_SYMBOL = '$'

Sekarang pengguna bisa meng-import langsung dari paket:

python
# Alih-alih: from data_tools.validators import is_valid_email
# Kamu bisa menulis:
from data_tools import is_valid_email, format_currency
 
print(is_valid_email("test@test.com"))  # Output: True
print(format_currency(99.99))           # Output: $99.99

22.6) Variabel __name__ dan if __name__ == "__main__": Menjalankan File sebagai Skrip

File Python bisa punya dua tujuan: bisa di-import sebagai modul atau dijalankan sebagai skrip mandiri. Variabel khusus __name__ membantu kamu menulis kode yang berfungsi baik untuk kedua situasi.

Memahami __name__

Setiap modul Python punya variabel bawaan bernama __name__. Python menyetel variabel ini secara berbeda tergantung bagaimana file digunakan:

  • Saat di-import: __name__ disetel ke nama modul
  • Saat dijalankan langsung: __name__ disetel ke "__main__"

Mari lihat ini secara langsung. Buat file bernama demo_name.py:

python
# demo_name.py
print(f"The __name__ variable is: {__name__}")

Sekarang jalankan langsung:

bash
python demo_name.py

Output:

The __name__ variable is: __main__

Sekarang import dari file lain:

python
# test_import.py
import demo_name

Output:

The __name__ variable is: demo_name

Saat kamu menjalankan demo_name.py secara langsung, Python menyetel __name__ menjadi "__main__". Saat kamu meng-import-nya, Python menyetel __name__ menjadi nama modul ("demo_name").

Pola if __name__ == "__main__":

Perilaku ini memungkinkan kamu menulis kode yang hanya berjalan saat file dieksekusi langsung, bukan saat di-import. Ini dilakukan dengan pola:

python
if __name__ == "__main__":
    # Kode di sini hanya berjalan saat file dieksekusi langsung
    pass

Berikut mengapa ini berguna. Buat math_utils.py:

python
# math_utils.py
"""Utility functions for mathematical operations."""
 
def calculate_area(radius):
    """Calculate the area of a circle."""
    return 3.14159 * radius ** 2
 
def calculate_circumference(radius):
    """Calculate the circumference of a circle."""
    return 2 * 3.14159 * radius
 
# Kode pengujian - hanya berjalan saat file dieksekusi langsung
if __name__ == "__main__":
    print("Testing math_utils functions...")
    
    test_radius = 5
    area = calculate_area(test_radius)
    circumference = calculate_circumference(test_radius)
    
    print(f"Radius: {test_radius}")
    print(f"Area: {area:.2f}")
    print(f"Circumference: {circumference:.2f}")

Saat kamu menjalankan file ini secara langsung:

bash
python math_utils.py

Output:

Testing math_utils functions...
Radius: 5
Area: 78.54
Circumference: 31.42

Namun saat kamu meng-import-nya:

python
# use_math_utils.py
import math_utils
# Kode pengujian tidak berjalan!
 
area = math_utils.calculate_area(10)
print(f"Area of circle: {area:.2f}")  # Output: Area of circle: 314.16

Kode pengujian dalam blok if __name__ == "__main__": tidak dieksekusi saat import. Ini memungkinkan kamu menyertakan kode uji, contoh, atau demonstrasi di modulmu tanpa memengaruhi kode yang meng-import modul tersebut.

Penggunaan Umum if __name__ == "__main__":

Pengujian dan Demonstrasi

Sertakan contoh yang menunjukkan cara menggunakan modulmu:

python
# string_tools.py
def reverse_string(text):
    """Reverse a string."""
    return text[::-1]
 
def count_vowels(text):
    """Count vowels in text."""
    vowels = 'aeiouAEIOU'
    return sum(1 for char in text if char in vowels)
 
if __name__ == "__main__":
    # Kode demonstrasi
    sample = "Hello, World!"
    
    print(f"Original: {sample}")
    print(f"Reversed: {reverse_string(sample)}")
    print(f"Vowels: {count_vowels(sample)}")

Di bab ini, kita sudah mempelajari cara mengorganisasi kode Python menggunakan modul dan paket. Kita membahas cara kerja sistem import, berbagai cara untuk meng-import kode, dan cara membuat modul serta paket kita sendiri. Kita juga mempelajari variabel __name__ dan pola if __name__ == "__main__": yang memungkinkan file berfungsi baik sebagai modul yang dapat di-import maupun skrip mandiri.

Alat-alat organisasi ini akan makin penting seiring program kamu berkembang. Di bab berikutnya, kita akan membahas cara menggunakan fungsi sebagai data dan menerapkan teknik pemrograman fungsional yang sederhana, dengan melanjutkan fondasi organisasi kode yang sudah kita bangun di sini.

© 2025. Primesoft Co., Ltd.
support@primesoft.ai