15. Tuple dan Range: Sequence Sederhana yang Immutable
Di Bab 14, kita mengeksplorasi list—tipe sequence Python yang serbaguna dan mutable. Sekarang kita akan membahas dua tipe sequence penting lainnya: tuple dan range. Jika list unggul untuk menyimpan kumpulan yang berubah seiring waktu, tuple menyediakan sequence yang immutable yang melindungi data dari modifikasi, dan range menawarkan cara yang hemat memori untuk merepresentasikan urutan angka.
Memahami kapan harus memakai setiap tipe sequence akan membuat programmu lebih efisien, lebih aman, dan lebih jelas maksudnya. Di akhir bab ini, kamu akan tahu cara bekerja dengan tuple dan range secara efektif, dan kamu akan memahami operasi umum yang bekerja di semua tipe sequence Python.
15.1) Membuat dan Menggunakan Tuple (Pentingnya Koma)
Sebuah tuple adalah sequence item yang terurut dan immutable. Seperti list, tuple bisa berisi tipe data apa pun dan mempertahankan urutan elemen. Namun, berbeda dengan list, setelah kamu membuat tuple, kamu tidak bisa memodifikasi isinya.
Membuat Tuple dengan Tanda Kurung
Cara paling umum untuk membuat tuple adalah dengan menaruh nilai yang dipisahkan koma di dalam tanda kurung:
# Tuple berisi nilai ujian siswa
scores = (85, 92, 78, 95)
print(scores) # Output: (85, 92, 78, 95)
print(type(scores)) # Output: <class 'tuple'>
# Tuple dengan tipe data campuran
student_info = ("Alice", 20, "Computer Science", 3.8)
print(student_info) # Output: ('Alice', 20, 'Computer Science', 3.8)
# Tuple kosong
empty = ()
print(empty) # Output: ()
print(len(empty)) # Output: 0Tuple memakai tanda kurung () untuk sintaks literalnya, sedangkan list memakai tanda kurung siku []. Perbedaan visual ini membantumu langsung mengenali tipe mana yang sedang kamu pakai.
Koma yang Membuat Tuple, Bukan Tanda Kurung
Ini detail penting yang mengejutkan banyak pemula: koma-lah yang sebenarnya membuat tuple, bukan tanda kurung. Tanda kurung sering kali opsional dan terutama berfungsi untuk membuat tuple lebih terlihat atau untuk mengelompokkannya dalam ekspresi.
# Ini semua membuat tuple yang sama
coordinates_1 = (10, 20)
coordinates_2 = 10, 20 # Tidak perlu tanda kurung!
print(coordinates_1) # Output: (10, 20)
print(coordinates_2) # Output: (10, 20)
print(coordinates_1 == coordinates_2) # Output: True
# Yang penting adalah komanya
x = (42) # Ini hanya integer 42 di dalam tanda kurung
y = (42,) # Ini tuple yang berisi satu elemen
print(type(x)) # Output: <class 'int'>
print(type(y)) # Output: <class 'tuple'>
print(y) # Output: (42,)Tanda kurung pada (42) hanya tanda kurung pengelompokan, seperti pada ekspresi matematika. Untuk membuat tuple satu elemen, kamu harus menyertakan koma di akhir: (42,). Koma ini memberi tahu Python bahwa kamu ingin tuple, bukan sekadar ekspresi yang dikelompokkan.
Kapan Tanda Kurung Diperlukan
Walaupun koma yang menciptakan tuple, tanda kurung menjadi wajib dalam situasi tertentu untuk menghindari ambiguitas:
# Tanpa tanda kurung, ini akan membingungkan
def get_dimensions():
return 1920, 1080 # Mengembalikan tuple
width, height = get_dimensions()
print(f"Screen: {width}x{height}") # Output: Screen: 1920x1080
# Tanda kurung diperlukan saat mengirim tuple sebagai argumen fungsi
print((1, 2, 3)) # Output: (1, 2, 3)
# Tanpa tanda kurung, Python akan melihat tiga argumen terpisah
# Tanda kurung diperlukan dalam ekspresi kompleks
result = (10, 20) + (30, 40) # Konkatenasi tuple
print(result) # Output: (10, 20, 30, 40)Membuat Tuple Satu Elemen
Kebutuhan koma di akhir untuk tuple satu elemen sering membuat pemula terkejut:
# Kesalahan umum: lupa koma
not_a_tuple = ("Python")
print(type(not_a_tuple)) # Output: <class 'str'>
print(not_a_tuple) # Output: Python
# Benar: sertakan koma di akhir
is_a_tuple = ("Python",)
print(type(is_a_tuple)) # Output: <class 'tuple'>
print(is_a_tuple) # Output: ('Python',)
# Koma bekerja bahkan tanpa tanda kurung
also_a_tuple = "Python",
print(type(also_a_tuple)) # Output: <class 'tuple'>
print(also_a_tuple) # Output: ('Python',)Kenapa Python membutuhkan sintaks yang tampak canggung ini? Karena tanda kurung sudah punya makna lain di Python—yaitu mengelompokkan ekspresi. Tanpa koma, Python tidak punya cara untuk membedakan antara (42) sebagai angka yang dikelompokkan dan (42) sebagai tuple.
Mengakses Elemen Tuple
Tuple mendukung operasi indexing dan slicing yang sama seperti list:
# Tuple informasi siswa
student = ("Bob", 22, "Physics", 3.6)
# Mengakses elemen individual (zero-indexed)
name = student[0]
age = student[1]
major = student[2]
gpa = student[3]
print(f"{name} is {age} years old") # Output: Bob is 22 years old
print(f"Major: {major}, GPA: {gpa}") # Output: Major: Physics, GPA: 3.6
# Indexing negatif juga bisa
last_item = student[-1]
print(f"Last item: {last_item}") # Output: Last item: 3.6
# Slicing mengekstrak tuple baru
first_two = student[:2]
print(first_two) # Output: ('Bob', 22)
print(type(first_two)) # Output: <class 'tuple'>Setiap teknik indexing dan slicing yang kamu pelajari dengan list di Bab 14 bekerja identik pada tuple. Perbedaan utamanya adalah tuple tidak bisa dimodifikasi setelah dibuat.
15.2) Packing dan Unpacking Tuple
Salah satu fitur tuple yang paling kuat dan elegan adalah kemampuannya untuk melakukan packing beberapa nilai bersama-sama dan meng-unpack-nya ke variabel terpisah. Fitur ini membuat kode Python sangat ringkas dan mudah dibaca.
Packing Tuple
Tuple packing terjadi saat kamu membuat tuple dengan menempatkan beberapa nilai bersama, dipisahkan oleh koma:
# Melakukan packing nilai ke dalam tuple
coordinates = 10, 20, 30
print(coordinates) # Output: (10, 20, 30)
# Packing tipe yang berbeda
user_data = "Alice", 25, "alice@example.com"
print(user_data) # Output: ('Alice', 25, 'alice@example.com')
# Packing nilai return dari fungsi
def get_statistics(numbers):
total = sum(numbers)
count = len(numbers)
average = total / count
return total, count, average # Melakukan packing tiga nilai ke dalam tuple
stats = get_statistics([85, 90, 78, 92, 88])
print(stats) # Output: (433, 5, 86.6)Saat sebuah fungsi mengembalikan beberapa nilai yang dipisahkan koma, Python otomatis melakukan packing nilai-nilai itu ke dalam tuple. Inilah sebabnya fungsi bisa terlihat seolah mengembalikan banyak nilai—padahal sebenarnya mengembalikan satu tuple yang berisi nilai-nilai tersebut.
Unpacking Tuple
Tuple unpacking adalah proses kebalikannya: mengekstrak nilai dari tuple ke variabel terpisah:
# Unpacking dasar
point = (100, 200)
x, y = point
print(f"x = {x}, y = {y}") # Output: x = 100, y = 200
# Unpacking bekerja untuk sequence apa pun, bukan hanya tuple
name, age, email = ["Bob", 30, "bob@example.com"]
print(f"{name} is {age} years old") # Output: Bob is 30 years old
# Unpacking langsung nilai return fungsi
total, count, average = get_statistics([95, 88, 92, 85])
print(f"Average of {count} scores: {average}") # Output: Average of 4 scores: 90.0Jumlah variabel di sisi kiri harus cocok dengan jumlah elemen dalam sequence. Jika tidak cocok, Python akan memunculkan ValueError:
# Ini akan menyebabkan error
coordinates = (10, 20, 30)
# x, y = coordinates # ValueError: too many values to unpack (expected 2)
# Ini juga akan menyebabkan error
point = (5, 10)
# x, y, z = point # ValueError: not enough values to unpack (expected 3, got 2)Menukar Variabel dengan Tuple Unpacking
Tuple unpacking memungkinkan cara elegan untuk menukar nilai variabel tanpa perlu variabel sementara:
# Pertukaran tradisional memakai variabel sementara
a = 10
b = 20
temp = a
a = b
b = temp
print(f"a = {a}, b = {b}") # Output: a = 20, b = 10
# Pertukaran elegan Python memakai tuple unpacking
x = 100
y = 200
x, y = y, x # Swap dalam satu baris!
print(f"x = {x}, y = {y}") # Output: x = 200, y = 100
# Menukar lebih dari dua variabel
first = "A"
second = "B"
third = "C"
first, second, third = third, first, second
print(first, second, third) # Output: C A BBagaimana ini bekerja? Python mengevaluasi sisi kanan terlebih dahulu, membuat tuple (y, x), lalu meng-unpack-nya ke variabel di sisi kiri. Ini terjadi dalam satu langkah, jadi tidak perlu variabel sementara.
Unpacking Diperluas dengan Operator Star
Python menyediakan extended unpacking menggunakan operator * untuk menangkap banyak elemen:
# Unpacking dengan variabel "sisa"
scores = (95, 88, 92, 85, 90, 87)
first, second, *rest = scores
print(f"Top two: {first}, {second}") # Output: Top two: 95, 88
print(f"Others: {rest}") # Output: Others: [92, 85, 90, 87]
print(type(rest)) # Output: <class 'list'>
# Star bisa muncul di mana saja
numbers = (1, 2, 3, 4, 5)
first, *middle, last = numbers
print(f"First: {first}") # Output: First: 1
print(f"Middle: {middle}") # Output: Middle: [2, 3, 4]
print(f"Last: {last}") # Output: Last: 5
# Menangkap bagian awal
*beginning, second_last, last = numbers
print(f"Beginning: {beginning}") # Output: Beginning: [1, 2, 3]
print(f"Last two: {second_last}, {last}") # Output: Last two: 4, 5Perhatikan bahwa variabel bertanda star selalu menangkap elemen sebagai list, bahkan saat melakukan unpacking dari tuple. Jika tidak ada elemen yang ditangkap, variabel bertanda star menjadi list kosong:
# Saat tidak ada yang bisa ditangkap
a, b, *rest = (10, 20)
print(rest) # Output: []
# Hanya satu star yang boleh per unpacking
# first, *middle, *end = (1, 2, 3, 4) # SyntaxError: multiple starred expressionsMengabaikan Nilai dengan Underscore
Kadang kamu hanya membutuhkan nilai tertentu dari sebuah tuple. Secara konvensi, programmer Python memakai underscore _ sebagai nama variabel untuk menandai nilai yang ingin diabaikan:
# Mem-parsing string tanggal
date_string = "2024-03-15"
year, month, day = date_string.split("-")
print(f"Month: {month}") # Output: Month: 03
# Jika kita hanya peduli pada bulan
_, month, _ = date_string.split("-")
print(f"Month: {month}") # Output: Month: 03
# Dengan extended unpacking
data = ("Alice", 25, "Engineer", "New York", "alice@example.com")
name, age, *_, email = data
print(f"{name} ({age}): {email}") # Output: Alice (25): alice@example.comUnderscore hanyalah nama variabel biasa, tetapi memakainya memberi sinyal ke programmer lain (dan dirimu sendiri) bahwa kamu sengaja mengabaikan nilai-nilai tersebut.
Contoh Praktis Packing dan Unpacking
# Mengembalikan beberapa nilai dari perhitungan
def calculate_rectangle_properties(width, height):
"""Calculate area and perimeter of a rectangle."""
area = width * height
perimeter = 2 * (width + height)
return area, perimeter # Packing
# Unpacking hasilnya
rect_area, rect_perimeter = calculate_rectangle_properties(5, 3)
print(f"Area: {rect_area}, Perimeter: {rect_perimeter}") # Output: Area: 15, Perimeter: 16
# Iterasi dengan unpacking
students = [
("Alice", 85),
("Bob", 92),
("Carol", 78)
]
for name, score in students: # Unpacking di dalam loop
print(f"{name}: {score}")
# Output:
# Alice: 85
# Bob: 92
# Carol: 78Tuple packing dan unpacking membuat kode Python lebih mudah dibaca dan lebih ekspresif. Alih-alih mengakses elemen tuple lewat indeks (student[0], student[1]), kamu bisa meng-unpack-nya ke variabel yang namanya lebih bermakna.
15.3) Tuple Itu Immutable: Kapan Itu Berguna
Karakteristik utama tuple adalah immutability-nya—setelah dibuat, isi tuple tidak bisa diubah. Kamu tidak bisa menambah, menghapus, atau memodifikasi elemen. Immutability ini mungkin terlihat seperti keterbatasan, tetapi sebenarnya memberi manfaat penting.
Apa Arti Immutability dalam Praktik
# Membuat tuple
coordinates = (10, 20, 30)
print(coordinates) # Output: (10, 20, 30)
# Mencoba memodifikasi akan memunculkan error
# coordinates[0] = 15 # TypeError: 'tuple' object does not support item assignment
# Mencoba menambah elemen akan memunculkan error
# coordinates.append(40) # AttributeError: 'tuple' object has no attribute 'append'
# Mencoba menghapus elemen akan memunculkan error
# del coordinates[1] # TypeError: 'tuple' object doesn't support item deletionSaat Python mengatakan tuple tidak mendukung item assignment, artinya kamu tidak bisa mengubah apa yang tersimpan pada posisi mana pun di tuple. Struktur tuple bersifat tetap saat dibuat.
Membandingkan List yang Mutable dan Tuple yang Immutable
# List bersifat mutable - kamu bisa mengubahnya
shopping_list = ["milk", "bread", "eggs"]
shopping_list[1] = "butter" # Memodifikasi elemen
shopping_list.append("cheese") # Menambahkan elemen
print(shopping_list) # Output: ['milk', 'butter', 'eggs', 'cheese']
# Tuple bersifat immutable - kamu tidak bisa mengubahnya
product_dimensions = (10, 20, 5) # width, height, depth in cm
# product_dimensions[0] = 12 # TypeError: cannot modify
# product_dimensions.append(3) # AttributeError: no append method
# Untuk "mengubah" tuple, kamu harus membuat yang baru
new_dimensions = (12, 20, 5) # Membuat tuple baru sepenuhnya
print(new_dimensions) # Output: (12, 20, 5)Kenapa Immutability Berguna
Immutability memberi beberapa manfaat praktis:
1. Integritas dan Keamanan Data
Saat kamu mengoper tuple ke sebuah fungsi(function), kamu tahu fungsi itu tidak bisa secara tidak sengaja memodifikasi datamu:
def calculate_distance(point1, point2):
"""Calculate distance between two 2D points."""
x1, y1 = point1
x2, y2 = point2
dx = x2 - x1
dy = y2 - y1
# Bahkan jika kita mau, kita tidak bisa memodifikasi tuple input
return (dx**2 + dy**2) ** 0.5
start = (0, 0)
end = (3, 4)
distance = calculate_distance(start, end)
print(f"Distance: {distance}") # Output: Distance: 5.0
print(f"Start point unchanged: {start}") # Output: Start point unchanged: (0, 0)Dengan list, kamu perlu khawatir apakah sebuah fungsi mungkin memodifikasi datamu. Dengan tuple, kamu punya jaminan bahwa itu tidak akan terjadi.
2. Menggunakan Tuple sebagai Key Dictionary
Seperti yang akan kita bahas lebih jauh di Bab 17, key dictionary harus hashable—mereka harus memiliki nilai hash yang tidak pernah berubah. Objek immutable seperti tuple bisa menjadi key dictionary; objek mutable seperti list tidak bisa:
# Tuple bisa menjadi key dictionary
locations = {
(0, 0): "Origin",
(10, 20): "Point A",
(30, 40): "Point B"
}
print(locations[(10, 20)]) # Output: Point A
# List tidak bisa menjadi key dictionary
# locations_bad = {
# [0, 0]: "Origin" # TypeError: unhashable type: 'list'
# }3. Memberi Sinyal Maksud (Intent)
Memakai tuple alih-alih list mengomunikasikan kepada programmer lain (dan dirimu sendiri) bahwa data ini seharusnya tidak berubah:
# Nilai warna RGB - ini seharusnya tidak pernah berubah
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# Parameter koneksi database - konfigurasi tetap
DB_CONFIG = ("localhost", 5432, "myapp", "production")
# Koordinat geografis - sebuah lokasi tidak berubah
EIFFEL_TOWER = (48.8584, 2.2945) # latitude, longitudeSaat kamu melihat tuple di kode, kamu langsung tahu data ini dimaksudkan untuk tetap konstan. Saat kamu melihat list, kamu tahu data itu mungkin akan dimodifikasi.
4. Manfaat Performa
Karena tuple bersifat immutable, Python bisa mengoptimalkannya dengan cara yang tidak bisa dilakukan pada list. Kita akan belajar tentang modul sys di Bab 27, tetapi untuk sekarang, cukup tahu bahwa sys.getsizeof() memberi tahu kita berapa banyak memori yang dipakai sebuah objek:
import sys
# Tuple memakai memori lebih sedikit daripada list yang setara
tuple_data = (1, 2, 3, 4, 5)
list_data = [1, 2, 3, 4, 5]
print(f"Tuple size: {sys.getsizeof(tuple_data)} bytes") # Output: Tuple size: 80 bytes (may vary by Python version)
print(f"List size: {sys.getsizeof(list_data)} bytes") # Output: List size: 104 bytes (may vary by Python version)
# Membuat tuple lebih cepat
import timeit
tuple_time = timeit.timeit("(1, 2, 3, 4, 5)", number=1000000)
list_time = timeit.timeit("[1, 2, 3, 4, 5]", number=1000000)
print(f"Tuple creation: {tuple_time:.4f} seconds")
print(f"List creation: {list_time:.4f} seconds")
# Example output: Tuple creation: 0.0055 seconds, List creation: 0.0292 seconds15.4) Jebakan Immutability: Saat Tuple Berisi Item yang Mutable
Walaupun tuple itu sendiri immutable, tuple bisa berisi objek mutable seperti list atau dictionary. Ini menciptakan perbedaan yang halus tetapi penting: struktur tuple tetap, tetapi isi objek mutable di dalamnya tetap bisa berubah.
Memahami Perbedaannya
# Tuple yang berisi list
student_data = ("Alice", 20, [85, 90, 78]) # name, age, scores
print(student_data) # Output: ('Alice', 20, [85, 90, 78])
# Kita tidak bisa menugaskan ulang elemen tuple
# student_data[0] = "Bob" # TypeError: 'tuple' object does not support item assignment
# Tapi kita BISA memodifikasi list di dalam tuple
student_data[2].append(92) # Menambahkan nilai baru
print(student_data) # Output: ('Alice', 20, [85, 90, 78, 92])
student_data[2][0] = 88 # Memodifikasi nilai yang sudah ada
print(student_data) # Output: ('Alice', 20, [88, 90, 78, 92])Apa yang terjadi di sini? Tuple menyimpan tiga referensi: satu ke string "Alice", satu ke integer 20, dan satu ke objek list. Struktur tuple—objek mana yang direferensikan—tidak bisa berubah. Tetapi objek list itu sendiri mutable, jadi isinya bisa berubah.
Memvisualisasikan Perbedaannya
# Struktur tuple bersifat tetap
data = ("Python", [1, 2, 3])
# Ini mencoba mengubah apa yang direferensikan tuple - TIDAK BOLEH
# data[1] = [4, 5, 6] # TypeError
# Ini memodifikasi list yang direferensikan tuple - BOLEH
data[1].append(4)
print(data) # Output: ('Python', [1, 2, 3, 4])
# Tuple masih mereferensikan objek list yang sama
# Hanya isi list yang berubah, bukan list mana yang ditunjuk tuplePikirkan seperti ini: tuple itu seperti barisan kotak, dan setiap kotak berisi referensi ke sebuah objek. Kotak-kotaknya terkunci di tempatnya (immutable), tetapi jika sebuah kotak berisi referensi ke objek mutable, objek itu tetap bisa berubah.
Tuple dengan Dictionary
Prinsip yang sama berlaku untuk dictionary di dalam tuple:
# Tuple yang berisi dictionary
user_profile = ("alice", {"email": "alice@example.com", "age": 25})
print(user_profile) # Output: ('alice', {'email': 'alice@example.com', 'age': 25})
# Tidak bisa mengubah dictionary mana yang direferensikan tuple
# user_profile[1] = {"email": "newemail@example.com"} # TypeError
# Tapi BISA memodifikasi dictionary itu sendiri
user_profile[1]["age"] = 26
user_profile[1]["city"] = "New York"
print(user_profile) # Output: ('alice', {'email': 'alice@example.com', 'age': 26, 'city': 'New York'})Kenapa Ini Penting untuk Key Dictionary
Tuple bisa dipakai sebagai key dictionary hanya jika semua elemennya hashable. Walaupun tuple itu sendiri immutable, tuple yang berisi objek mutable (seperti list) sama sekali tidak hashable dan karena itu tidak bisa digunakan sebagai key dictionary.
# Ini bekerja tapi berbahaya
tuple_with_list = ("key", [1, 2, 3])
# data = {tuple_with_list: "value"} # TypeError: unhashable type: 'list'Hanya gunakan tuple yang berisi objek yang sepenuhnya immutable (string, number, frozenset, tuple lain) sebagai key dictionary.
Membuat Tuple yang Benar-Benar Immutable
Jika kamu butuh tuple yang sepenuhnya immutable, pastikan semua isinya juga immutable:
# Tuple yang sepenuhnya immutable - hanya tipe immutable
point_3d = (10, 20, 30) # Semua integer
rgb_color = (255, 128, 0) # Semua integer
coordinates = ((10, 20), (30, 40)) # Tuple berisi tuple
# Ini aman dipakai sebagai key dictionary
color_names = {
(255, 0, 0): "Red",
(0, 255, 0): "Green",
(0, 0, 255): "Blue"
}
# Tuple bertingkat tetap immutable
nested = ((1, 2), (3, 4))
# nested[0][0] = 5 # TypeError: 'tuple' object does not support item assignmentSaat Isi Mutable Memang Disengaja
Kadang kamu memang menginginkan tuple dengan isi mutable—misalnya, saat kamu punya struktur record yang tetap tetapi satu field perlu berubah:
# Catatan siswa dengan identitas tetap tetapi nilai yang berubah
def create_student(name, student_id):
"""Create a student record with empty grade list."""
return (name, student_id, []) # name dan ID tetap, grades bisa berubah
student = create_student("Alice", "S12345")
print(student) # Output: ('Alice', 'S12345', [])
# Identitas siswa tetap
print(f"Student: {student[0]} (ID: {student[1]})") # Output: Student: Alice (ID: S12345)
# Tapi kita bisa menambahkan nilai saat didapatkan
student[2].append(85)
student[2].append(92)
student[2].append(78)
print(f"Grades: {student[2]}") # Output: Grades: [85, 92, 78]
# Struktur tuple melindungi name dan ID dari perubahan yang tidak sengaja
# sambil tetap memungkinkan list nilai bertambahPola ini berguna saat kamu ingin melindungi sebagian data sambil tetap memungkinkan data lain berubah. Hanya pastikan kamu paham perbedaan antara immutability tuple dan mutability isinya.
15.5) Kapan Menggunakan Tuple Alih-alih List
Memilih antara tuple dan list adalah keputusan desain yang penting. Walaupun keduanya sama-sama sequence, mereka punya tujuan berbeda dan mengomunikasikan maksud yang berbeda.
Gunakan Tuple untuk Data Tetap yang Heterogen
Tuple paling cocok saat kamu punya jumlah item yang tetap yang merepresentasikan satu entitas logis, sering kali dengan tipe yang berbeda:
# Catatan siswa: name, age, major, GPA
student = ("Alice", 20, "Computer Science", 3.8)
# Koordinat geografis: latitude, longitude
location = (40.7128, -74.0060) # New York City
# Warna RGB: red, green, blue
color = (255, 128, 0)
# Koneksi database: host, port, database, username
db_connection = ("localhost", 5432, "myapp", "admin")
# Tanggal: year, month, day
date = (2024, 3, 15)Setiap tuple merepresentasikan sebuah "record" lengkap di mana posisi tiap elemen punya makna spesifik. Elemen pertama selalu name, yang kedua selalu age, dan seterusnya.
Gunakan List untuk Koleksi Homogen
List paling cocok saat kamu punya jumlah item yang bervariasi dari item-item serupa yang mungkin akan kamu tambah, hapus, atau urutkan ulang:
# Daftar belanja - item dengan tipe yang sama (string)
shopping_list = ["milk", "bread", "eggs", "butter"]
shopping_list.append("cheese") # Tambah item sesuai kebutuhan
shopping_list.remove("bread") # Hapus item
# Nilai ujian - item dengan tipe yang sama (number)
test_scores = [85, 92, 78, 95, 88]
test_scores.append(90) # Tambah nilai baru
test_scores.sort() # Mengurutkan ulang nilai
# Nama pengguna - item dengan tipe yang sama (string)
active_users = ["alice", "bob", "carol"]
active_users.extend(["dave", "eve"]) # Tambah banyak pengguna sekaligusList untuk koleksi di mana jumlah item mungkin berubah dan di mana setiap item punya peran yang sama.
Tuple untuk Nilai Return Fungsi
Saat sebuah fungsi mengembalikan beberapa nilai yang saling terkait, tuple adalah pilihan alami:
def get_user_info(user_id):
"""Retrieve user information from database."""
# Simulasikan pencarian database
return "Alice", "alice@example.com", 25, "New York"
# Unpack tuple yang dikembalikan
name, email, age, city = get_user_info(101)
print(f"{name} from {city}") # Output: Alice from New York
def calculate_statistics(numbers):
"""Calculate min, max, and average of numbers."""
if not numbers:
return None, None, None
minimum = min(numbers)
maximum = max(numbers)
average = sum(numbers) / len(numbers)
return minimum, maximum, average
# Unpack hasilnya
min_val, max_val, avg_val = calculate_statistics([85, 92, 78, 95, 88])
print(f"Range: {min_val} to {max_val}, Average: {avg_val}")
# Output: Range: 78 to 95, Average: 87.6Mengembalikan tuple membuat jelas bahwa nilai-nilai ini saling terkait dan seharusnya dipertimbangkan bersama.
Tuple untuk Key Dictionary
Saat kamu butuh key gabungan (composite keys) di dictionary, tuple itu penting:
# Nilai siswa berdasarkan mata kuliah dan semester
grades = {
("CS101", "Fall2023"): 85,
("CS101", "Spring2024"): 90,
("MATH201", "Fall2023"): 88,
("MATH201", "Spring2024"): 92
}
# Cari nilai tertentu
course = "CS101"
semester = "Spring2024"
grade = grades[(course, semester)]
print(f"Grade in {course} ({semester}): {grade}") # Output: Grade in CS101 (Spring2024): 90
# Koordinat grid sebagai key dictionary
grid = {
(0, 0): "Start",
(5, 3): "Obstacle",
(10, 10): "Goal"
}
position = (5, 3)
if position in grid:
print(f"At {position}: {grid[position]}") # Output: At (5, 3): ObstacleList tidak bisa menjadi key dictionary karena mutable, tetapi tuple bisa.
Tuple untuk Konfigurasi yang Immutable
Saat kamu punya data konfigurasi yang seharusnya tidak pernah berubah, tuple memberi sinyal maksud ini:
# Pengaturan aplikasi yang seharusnya tetap konstan
APP_CONFIG = (
"MyApp", # Nama aplikasi
"1.0.0", # Versi
"production", # Environment
True, # Mode debug
8080 # Port
)
# Palet warna untuk UI - warna-warna ini tetap
COLOR_PALETTE = (
(255, 0, 0), # Merah utama
(0, 128, 255), # Biru utama
(255, 255, 255), # Putih
(0, 0, 0) # Hitam
)
# Endpoint API - URL ini tidak berubah
API_ENDPOINTS = (
"https://api.example.com/users",
"https://api.example.com/products",
"https://api.example.com/orders"
)Panduan Keputusan
# Gunakan TUPLE saat:
# 1. Data merepresentasikan satu record dengan struktur tetap
employee = ("E001", "Alice", "Engineering", 75000)
# 2. Mengembalikan beberapa nilai dari sebuah fungsi
def divide_with_remainder(a, b):
return a // b, a % b
# 3. Perlu dipakai sebagai key dictionary
cache = {(5, 10): 50, (3, 7): 21}
# 4. Data tidak boleh dimodifikasi
SCREEN_RESOLUTION = (1920, 1080)
# Gunakan LIST saat:
# 1. Koleksi item serupa yang mungkin berubah
tasks = ["Write code", "Test code", "Deploy code"]
tasks.append("Document code")
# 2. Perlu menambah, menghapus, atau mengurutkan ulang item
scores = [85, 90, 78]
scores.sort()
scores.append(92)
# 3. Semua item punya tujuan yang sama
usernames = ["alice", "bob", "carol"]
# 4. Ukuran koleksi tidak diketahui sebelumnya
results = []
for i in range(10):
results.append(i * 2)15.6) Memahami Objek range secara Mendalam
Sekarang setelah kita memahami kapan memakai tuple dibanding list, mari kita bahas tipe sequence immutable ketiga di Python: range. Tipe range merepresentasikan sequence angka yang immutable. Berbeda dengan list dan tuple yang menyimpan semua elemennya di memori, objek range menghasilkan angka saat dibutuhkan, sehingga sangat hemat memori untuk merepresentasikan sequence angka.
Membuat Objek range
Fungsi range() membuat objek range dengan tiga bentuk:
# Satu argumen: range(stop)
# Menghasilkan angka dari 0 sampai (tapi tidak termasuk) stop
numbers = range(5)
print(list(numbers)) # Output: [0, 1, 2, 3, 4]
# Dua argumen: range(start, stop)
# Menghasilkan angka dari start sampai (tapi tidak termasuk) stop
numbers = range(2, 7)
print(list(numbers)) # Output: [2, 3, 4, 5, 6]
# Tiga argumen: range(start, stop, step)
# Menghasilkan angka dari start sampai stop, bertambah sebesar step
numbers = range(0, 10, 2)
print(list(numbers)) # Output: [0, 2, 4, 6, 8]
# Step negatif untuk menghitung mundur
numbers = range(10, 0, -1)
print(list(numbers)) # Output: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]Perhatikan bahwa kita mengonversi range menjadi list dengan list() untuk melihat isinya. Objek range itu sendiri tidak menampilkan semua nilainya saat dicetak:
r = range(5)
print(r) # Output: range(0, 5)
print(type(r)) # Output: <class 'range'>Cara Kerja Objek range
Objek range tidak menyimpan semua nilainya di memori. Sebaliknya, ia menghitung setiap nilai saat dibutuhkan:
import sys
# Range yang merepresentasikan sejuta angka
large_range = range(1000000)
print(f"Range size: {sys.getsizeof(large_range)} bytes") # Output: Range size: 48 bytes (may vary by Python version)
# List yang berisi sejuta angka
large_list = list(range(1000000))
print(f"List size: {sys.getsizeof(large_list)} bytes") # Output: List size: 8000056 bytes (approximately 8MB)
# Range itu kecil; list itu besar!Objek range hanya menyimpan tiga nilai: start, stop, dan step. Ia menghitung setiap angka dalam sequence saat kamu memintanya. Ini membuat range sangat efisien untuk sequence besar.
Menggunakan range dalam for Loop
Seperti yang kita pelajari di Bab 12, range paling sering dipakai dengan for loop:
# Menghitung dari 0 sampai 4
for i in range(5):
print(f"Count: {i}")
# Output:
# Count: 0
# Count: 1
# Count: 2
# Count: 3
# Count: 4
# Menghitung dari 1 sampai 10
for i in range(1, 11):
print(i, end=" ")
print() # Output: 1 2 3 4 5 6 7 8 9 10
# Menghitung per dua
for i in range(0, 20, 2):
print(i, end=" ")
print() # Output: 0 2 4 6 8 10 12 14 16 18
# Menghitung mundur
for i in range(5, 0, -1):
print(f"T-minus {i}")
# Output:
# T-minus 5
# T-minus 4
# T-minus 3
# T-minus 2
# T-minus 1Indexing dan Slicing pada Objek range
Objek range mendukung indexing dan slicing seperti sequence lainnya:
# Membuat range
numbers = range(10, 50, 5) # 10, 15, 20, 25, 30, 35, 40, 45
# Indexing
print(numbers[0]) # Output: 10
print(numbers[3]) # Output: 25
print(numbers[-1]) # Output: 45
# Slicing mengembalikan range baru
subset = numbers[2:5]
print(subset) # Output: range(20, 35, 5)
print(list(subset)) # Output: [20, 25, 30]
# Panjang
print(len(numbers)) # Output: 8Mengecek Keanggotaan (Membership)
Kamu bisa mengecek apakah sebuah angka ada di dalam range menggunakan operator in:
# Angka genap dari 0 sampai 20
evens = range(0, 21, 2)
print(10 in evens) # Output: True
print(15 in evens) # Output: False
print(20 in evens) # Output: True
# Ini sangat efisien - Python tidak menghasilkan semua angka
# Ia menghitung apakah angka tersebut akan ada dalam sequence
large_range = range(0, 1000000, 3)
print(999999 in large_range) # Output: True (instant, no iteration needed)Python bisa menentukan keanggotaan secara matematis tanpa menghasilkan semua angka, sehingga operasi ini sangat cepat bahkan untuk range yang sangat besar.
Range Kosong dan Range Terbalik
# Range kosong - stop sama dengan start
empty = range(5, 5)
print(list(empty)) # Output: []
print(len(empty)) # Output: 0
# Range kosong - tidak mungkin mencapai stop dengan step yang diberikan
impossible = range(1, 10, -1) # Tidak bisa menghitung naik dengan step negatif
print(list(impossible)) # Output: []
# Range terbalik
backwards = range(10, 0, -1)
print(list(backwards)) # Output: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
# Terbalik dengan angka negatif
negative_range = range(-5, -15, -2)
print(list(negative_range)) # Output: [-5, -7, -9, -11, -13]Kapan Menggunakan range vs List
# Gunakan range saat:
# 1. Kamu butuh sequence angka untuk iterasi
for i in range(100):
# Proses sesuatu 100 kali
pass
# 2. Kamu butuh indeks untuk sebuah sequence
items = ["a", "b", "c", "d"]
for i in range(len(items)):
print(f"Index {i}: {items[i]}")
# 3. Efisiensi memori penting untuk sequence besar
# Ini memakai memori minimal
for i in range(1000000):
if i % 100000 == 0:
print(i)
# Gunakan list saat:
# 1. Kamu perlu menyimpan nilai sebenarnya
squares = [1, 3, 5, 7, 10]
# 2. Kamu perlu memodifikasi sequence
numbers = list(range(5))
numbers[2] = 100 # Memodifikasi nilai
numbers.append(200) # Menambahkan nilai
# 3. Kamu perlu memakai sequence berkali-kali dengan operasi berbeda
data = list(range(10))
print(sum(data))
print(max(data))
print(sorted(data, reverse=True))Objek range adalah contoh sempurna efisiensi Python. Mereka memberikan semua manfaat sequence tanpa biaya memori untuk menyimpan setiap elemen.
15.7) Mengonversi antara List, Tuple, dan Range
Python memudahkan konversi antar tipe sequence yang berbeda. Memahami konversi ini membantumu memilih tipe yang tepat untuk setiap situasi dan mentransformasi data sesuai kebutuhan.
Mengonversi ke List
Fungsi list() mengonversi sequence apa pun menjadi list:
# Tuple ke list
student_tuple = ("Alice", 20, "CS")
student_list = list(student_tuple)
print(student_list) # Output: ['Alice', 20, 'CS']
print(type(student_list)) # Output: <class 'list'>
# Sekarang kita bisa memodifikasinya
student_list[1] = 21
student_list.append(3.8)
print(student_list) # Output: ['Alice', 21, 'CS', 3.8]
# Range ke list
numbers = range(5)
numbers_list = list(numbers)
print(numbers_list) # Output: [0, 1, 2, 3, 4]
# String ke list (setiap karakter menjadi elemen)
text = "Python"
chars = list(text)
print(chars) # Output: ['P', 'y', 't', 'h', 'o', 'n']Mengonversi ke list berguna saat kamu perlu memodifikasi sebuah sequence atau saat kamu perlu memakai metode khusus list seperti append(), sort(), atau remove().
Mengonversi ke Tuple
Fungsi tuple() mengonversi sequence apa pun menjadi tuple:
# List ke tuple
scores_list = [85, 90, 78, 92]
scores_tuple = tuple(scores_list)
print(scores_tuple) # Output: (85, 90, 78, 92)
print(type(scores_tuple)) # Output: <class 'tuple'>
# Sekarang ini immutable
# scores_tuple[0] = 88 # TypeError: 'tuple' object does not support item assignment
# Range ke tuple
numbers = range(1, 6)
numbers_tuple = tuple(numbers)
print(numbers_tuple) # Output: (1, 2, 3, 4, 5)
# String ke tuple
text = "Hi"
chars_tuple = tuple(text)
print(chars_tuple) # Output: ('H', 'i')Mengonversi ke tuple berguna saat kamu ingin melindungi data dari modifikasi atau saat kamu perlu memakai sebuah sequence sebagai key dictionary.
15.8) Operasi Sequence Umum di String, List, Tuple, dan Range
Tipe sequence Python—string, list, tuple, dan range—berbagi banyak operasi umum. Memahami operasi yang sama ini membantumu bekerja secara efisien dengan tipe sequence apa pun.
Panjang, Minimum, dan Maksimum
Semua sequence mendukung fungsi len(), min(), dan max():
# String
text = "Python"
print(len(text)) # Output: 6
print(min(text)) # Output: P (karakter terkecil berdasarkan nilai Unicode)
print(max(text)) # Output: y (karakter terbesar berdasarkan nilai Unicode)
# List
numbers = [45, 12, 78, 23, 56]
print(len(numbers)) # Output: 5
print(min(numbers)) # Output: 12
print(max(numbers)) # Output: 78
# Tuple
scores = (85, 92, 78, 95, 88)
print(len(scores)) # Output: 5
print(min(scores)) # Output: 78
print(max(scores)) # Output: 95
# Range
nums = range(10, 50, 5)
print(len(nums)) # Output: 8
print(min(nums)) # Output: 10
print(max(nums)) # Output: 45Agar min() dan max() bisa bekerja, elemen-elemen harus bisa dibandingkan. Kamu tidak bisa mencari minimum dari list yang berisi string dan number sekaligus:
mixed = [1, "hello", 3]
# print(min(mixed)) # TypeError: '<' not supported between instances of 'str' and 'int'Indexing dan Indexing Negatif
Semua sequence mendukung indexing dengan indeks positif dan negatif:
# Indexing positif (0-based)
text = "Python"
numbers = [10, 20, 30, 40, 50]
coords = (5, 10, 15)
values = range(0, 100, 10)
print(text[0]) # Output: P
print(numbers[2]) # Output: 30
print(coords[1]) # Output: 10
print(values[3]) # Output: 30
# Indexing negatif (dari akhir)
print(text[-1]) # Output: n (karakter terakhir)
print(numbers[-2]) # Output: 40 (kedua dari akhir)
print(coords[-3]) # Output: 5 (ketiga dari akhir, yaitu yang pertama)
print(values[-1]) # Output: 90 (nilai terakhir dalam range)Indeks negatif menghitung dari akhir: -1 adalah elemen terakhir, -2 adalah elemen kedua dari terakhir, dan seterusnya.
Uji Keanggotaan dengan in dan not in
Semua sequence mendukung uji keanggotaan:
# String - mengecek substring
text = "Python Programming"
print("Python" in text) # Output: True
print("Java" in text) # Output: False
print("gram" in text) # Output: True (substring)
print("PYTHON" not in text) # Output: True (case-sensitive)
# List
fruits = ["apple", "banana", "cherry", "date"]
print("banana" in fruits) # Output: True
print("grape" in fruits) # Output: False
print("apple" not in fruits) # Output: False
# Tuple
coordinates = (10, 20, 30, 40)
print(20 in coordinates) # Output: True
print(25 in coordinates) # Output: False
print(50 not in coordinates) # Output: True
# Range - sangat efisien, tidak perlu iterasi
numbers = range(0, 100, 2) # Angka genap 0 sampai 98
print(50 in numbers) # Output: True
print(51 in numbers) # Output: False (angka ganjil)
print(100 in numbers) # Output: False (stop bersifat eksklusif)Untuk range, Python bisa menentukan keanggotaan secara matematis tanpa mengecek setiap elemen, membuatnya sangat cepat bahkan untuk range besar.
Konkatenasi dan Repetisi
String, list, dan tuple mendukung konkatenasi dengan + dan repetisi dengan *:
# Konkatenasi dengan +
text1 = "Hello"
text2 = " World"
print(text1 + text2) # Output: Hello World
list1 = [1, 2, 3]
list2 = [4, 5, 6]
print(list1 + list2) # Output: [1, 2, 3, 4, 5, 6]
tuple1 = (10, 20)
tuple2 = (30, 40)
print(tuple1 + tuple2) # Output: (10, 20, 30, 40)
# Repetisi dengan *
print("Ha" * 3) # Output: HaHaHa
print([0] * 5) # Output: [0, 0, 0, 0, 0]
print((1, 2) * 3) # Output: (1, 2, 1, 2, 1, 2)Penting: Range tidak mendukung konkatenasi atau repetisi:
r1 = range(5)
r2 = range(5, 10)
# combined = r1 + r2 # TypeError: unsupported operand type(s) for +: 'range' and 'range'
# Untuk menggabungkan range, konversi ke list atau tuple terlebih dulu
combined = list(r1) + list(r2)
print(combined) # Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]Menghitung Kemunculan
Metode count() mengembalikan berapa kali sebuah elemen muncul:
# String - menghitung kemunculan substring
text = "Mississippi"
print(text.count("s")) # Output: 4
print(text.count("ss")) # Output: 2
print(text.count("i")) # Output: 4
# List
numbers = [1, 2, 3, 2, 4, 2, 5]
print(numbers.count(2)) # Output: 3
print(numbers.count(6)) # Output: 0
# Tuple
grades = (85, 90, 85, 92, 85, 88)
print(grades.count(85)) # Output: 3
print(grades.count(95)) # Output: 0
# Range tidak punya metode count(), tapi kamu bisa konversi dulu
nums = range(0, 20, 2)
nums_list = list(nums)
print(nums_list.count(10)) # Output: 1Menemukan Index Elemen
Metode index() mengembalikan posisi kemunculan pertama:
# String
text = "Python Programming"
print(text.index("P")) # Output: 0 (P pertama)
print(text.index("Pro")) # Output: 7 (posisi substring)
# print(text.index("Java")) # ValueError: substring not found
# List
fruits = ["apple", "banana", "cherry", "banana"]
print(fruits.index("banana")) # Output: 1 (kemunculan pertama)
print(fruits.index("cherry")) # Output: 2
# print(fruits.index("grape")) # ValueError: 'grape' is not in list
# Tuple
coordinates = (10, 20, 30, 20, 40)
print(coordinates.index(20)) # Output: 1 (kemunculan pertama)
print(coordinates.index(40)) # Output: 4
# Range tidak punya metode index(), tapi kamu bisa konversi dulu
nums = range(10, 50, 5)
nums_list = list(nums)
print(nums_list.index(25)) # Output: 3Jika elemennya tidak ditemukan, index() memunculkan ValueError. Untuk menghindarinya, cek dulu dengan in:
fruits = ["apple", "banana", "cherry"]
search_fruit = "grape"
if search_fruit in fruits:
position = fruits.index(search_fruit)
print(f"{search_fruit} found at position {position}")
else:
print(f"{search_fruit} not found")
# Output: grape not foundIterasi dengan for Loop
Semua sequence bisa diiterasi dengan for loop:
# String - iterasi per karakter
for char in "Python":
print(char, end=" ")
print() # Output: P y t h o n
# List
for fruit in ["apple", "banana", "cherry"]:
print(f"I like {fruit}")
# Output:
# I like apple
# I like banana
# I like cherry
# Tuple
for score in (85, 90, 78):
print(f"Score: {score}")
# Output:
# Score: 85
# Score: 90
# Score: 78
# Range
for i in range(1, 6):
print(f"Count: {i}")
# Output:
# Count: 1
# Count: 2
# Count: 3
# Count: 4
# Count: 5Operasi Perbandingan
Sequence bisa dibandingkan menggunakan ==, !=, <, >, <=, dan >=:
# Kesetaraan
print([1, 2, 3] == [1, 2, 3]) # Output: True
print((1, 2, 3) == (1, 2, 3)) # Output: True
print("abc" == "abc") # Output: True
# Ketidaksamaan
print([1, 2, 3] != [1, 2, 4]) # Output: True
print((1, 2) != (1, 2)) # Output: False
# Perbandingan leksikografis (elemen demi elemen)
print([1, 2, 3] < [1, 2, 4]) # Output: True (3 < 4)
print([1, 2, 3] < [1, 3, 0]) # Output: True (2 < 3)
print("apple" < "banana") # Output: True (alfabetis)
print((1, 2) < (1, 2, 3)) # Output: True (lebih pendek lebih kecil jika sejauh ini sama)
# Membandingkan tipe yang berbeda
print([1, 2, 3] == (1, 2, 3)) # Output: False (tipe berbeda)Perbandingan bekerja elemen demi elemen dari kiri ke kanan. Elemen pertama yang berbeda menentukan hasilnya.
Memahami operasi umum ini memungkinkan kamu menulis kode yang bekerja dengan tipe sequence apa pun, sehingga programmu lebih fleksibel dan dapat digunakan ulang.
15.9) Slicing Lanjutan di Semua Tipe Sequence
Slicing adalah salah satu fitur Python paling kuat untuk bekerja dengan sequence. Walaupun kita sudah mengenalkan slicing dasar di Bab 14, ada teknik slicing lanjutan yang bekerja di semua tipe sequence.
Tinjauan Slicing Dasar
Slicing mengekstrak sebagian sequence dengan sintaks sequence[start:stop:step]:
# Slicing dasar pada string
text = "Python Programming"
print(text[0:6]) # Output: Python
print(text[7:18]) # Output: Programming
print(text[7:]) # Output: Programming (dari index 7 sampai akhir)
print(text[:6]) # Output: Python (dari awal sampai index 6)
# Slicing dasar pada list
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[2:7]) # Output: [2, 3, 4, 5, 6]
print(numbers[:5]) # Output: [0, 1, 2, 3, 4]
print(numbers[5:]) # Output: [5, 6, 7, 8, 9]
# Slicing dasar pada tuple
coordinates = (10, 20, 30, 40, 50, 60)
print(coordinates[1:4]) # Output: (20, 30, 40)
print(coordinates[:3]) # Output: (10, 20, 30)
print(coordinates[3:]) # Output: (40, 50, 60)
# Slicing dasar pada range
nums = range(0, 100, 10)
print(list(nums[2:5])) # Output: [20, 30, 40]Ingat: start bersifat inklusif, stop bersifat eksklusif, dan hasilnya selalu bertipe sama seperti sequence aslinya.
Menggunakan Step dalam Slicing
Parameter ketiga opsional step mengontrol berapa elemen yang dilewati:
# Setiap elemen kedua
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[::2]) # Output: [0, 2, 4, 6, 8]
print(numbers[1::2]) # Output: [1, 3, 5, 7, 9]
# Setiap elemen ketiga
text = "abcdefghijklmnop"
print(text[::3]) # Output: adgjmp
# Step dengan start dan stop
print(numbers[2:8:2]) # Output: [2, 4, 6]
print(text[1:10:2]) # Output: bdfhjStep Negatif: Membalik Sequence
Step negatif membalik arah slicing:
# Membalik seluruh sequence
text = "Python"
print(text[::-1]) # Output: nohtyP
numbers = [1, 2, 3, 4, 5]
print(numbers[::-1]) # Output: [5, 4, 3, 2, 1]
coordinates = (10, 20, 30, 40)
print(coordinates[::-1]) # Output: (40, 30, 20, 10)
# Membalik dengan step
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[::-2]) # Output: [9, 7, 5, 3, 1] (setiap elemen kedua, mundur)
# Membalik sebagian
text = "Python Programming"
print(text[7:18][::-1]) # Output: gnimmargorP (balik "Programming")Saat memakai step negatif, start dan stop bekerja berbeda:
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Dengan step negatif, start harus lebih besar daripada stop
print(numbers[7:2:-1]) # Output: [7, 6, 5, 4, 3] (dari 7 turun sampai 3)
print(numbers[8:3:-2]) # Output: [8, 6, 4] (dari 8 turun sampai 4, step -2)
# Mengosongkan start/stop dengan step negatif
print(numbers[:5:-1]) # Output: [9, 8, 7, 6] (dari akhir turun sampai 6)
print(numbers[5::-1]) # Output: [5, 4, 3, 2, 1, 0] (dari 5 turun sampai awal)Indeks Negatif dalam Slicing
Kamu bisa memakai indeks negatif untuk posisi start dan stop:
text = "Python Programming"
# 11 karakter terakhir
print(text[-11:]) # Output: Programming
# Semua kecuali 11 karakter terakhir
print(text[:-11]) # Output: Python
# Dari -15 sampai -5
print(text[-15:-5]) # Output: hon Progra
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 5 elemen terakhir
print(numbers[-5:]) # Output: [5, 6, 7, 8, 9]
# Semua kecuali 3 elemen terakhir
print(numbers[:-3]) # Output: [0, 1, 2, 3, 4, 5, 6]
# Dari -7 sampai -2
print(numbers[-7:-2]) # Output: [3, 4, 5, 6, 7]Slicing pada Range
Slicing sebuah range mengembalikan objek range baru:
# Slicing range
numbers = range(0, 100, 5) # 0, 5, 10, 15, ..., 95
print(numbers) # Output: range(0, 100, 5)
# Slice mengembalikan range baru
subset = numbers[5:10]
print(subset) # Output: range(25, 50, 5)
print(list(subset)) # Output: [25, 30, 35, 40, 45]
# Dengan step
every_other = numbers[::2]
print(list(every_other)) # Output: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
# Step negatif
reversed_range = numbers[::-1]
print(list(reversed_range)) # Output: [95, 90, 85, ..., 5, 0]Slice Kosong dan Edge Case
numbers = [1, 2, 3, 4, 5]
# Slice kosong (start >= stop dengan step positif)
print(numbers[3:3]) # Output: []
print(numbers[5:10]) # Output: [] (stop melebihi panjang)
print(numbers[10:20]) # Output: [] (keduanya melebihi panjang)
# Slice melewati batas sequence aman
print(numbers[-100:100]) # Output: [1, 2, 3, 4, 5] (seluruh sequence)
print(numbers[2:100]) # Output: [3, 4, 5] (dari 2 sampai akhir)
# Step negatif dengan start/stop yang tidak kompatibel
print(numbers[2:7:-1]) # Output: [] (tidak bisa maju dengan step negatif)
# Step 0 tidak diizinkan
# print(numbers[::0]) # ValueError: slice step cannot be zeroSlicing untuk Menyalin (Copy)
Slicing membuat sequence baru, yang menyediakan cara untuk menyalin:
# Menyalin dengan slicing
original = [1, 2, 3, 4, 5]
copy = original[:] # Slice dari awal sampai akhir
print(copy) # Output: [1, 2, 3, 4, 5]
# Memodifikasi salinan tidak memengaruhi original
copy[0] = 100
print(f"Original: {original}") # Output: Original: [1, 2, 3, 4, 5]
print(f"Copy: {copy}") # Output: Copy: [100, 2, 3, 4, 5]
# Ini juga berlaku untuk tuple (membuat tuple baru)
original_tuple = (1, 2, 3, 4, 5)
copy_tuple = original_tuple[:]
print(copy_tuple) # Output: (1, 2, 3, 4, 5)
# Untuk string
text = "Python"
text_copy = text[:]
print(text_copy) # Output: PythonNamun, ingat dari Bab 14 bahwa ini membuat shallow copy.
# Keterbatasan shallow copy
original = [[1, 2], [3, 4]]
copy = original[:]
# Memodifikasi list bertingkat memengaruhi keduanya
copy[0][0] = 100
print(f"Original: {original}") # Output: Original: [[100, 2], [3, 4]]
print(f"Copy: {copy}") # Output: Copy: [[100, 2], [3, 4]]Tuple dan range adalah alat penting dalam toolkit sequence Python. Tuple menyediakan data terstruktur yang immutable yang melindungi informasi dari modifikasi yang tidak sengaja dan memungkinkan penggunaannya sebagai key dictionary. Range menawarkan representasi sequence angka yang hemat memori, sempurna untuk loop dan sequence besar. Memahami kapan memakai tiap tipe—dan cara mengonversi antar tipe—membuat kodemu lebih efisien, lebih aman, dan lebih jelas maksudnya.
Operasi umum yang dibagikan di semua tipe sequence—indexing, slicing, iterasi, uji keanggotaan—membentuk antarmuka yang konsisten yang membuat bekerja dengan sequence apa pun terasa intuitif. Teknik slicing lanjutan memberimu cara yang kuat dan ekspresif untuk mengekstrak dan memanipulasi data sequence.
Seiring kamu terus memprogram dengan Python, kamu akan terbiasa memilih tipe sequence yang tepat untuk tiap situasi: list untuk koleksi yang berubah, tuple untuk record yang tetap, range untuk sequence angka, dan string untuk teks. Bab ini telah memberimu pengetahuan untuk membuat pilihan itu dengan percaya diri dan memakai tiap tipe secara efektif.