26. Method dan self — Solusi pekerjaan rumah

File solusi .py ada di exercises/26/homework/solutions/.

Soal 1 — Object Counter

Soal. Class Counter dengan method inc, get, dan reset.

Cara berpikir. Object menyimpan state di self.count; setiap method membaca atau mengubahnya. Python meneruskan object sebagai self secara otomatis ketika kamu memanggil method pada sebuah instance.

Solusi.

class Counter:
    def __init__(self):
        self.count = 0

    def inc(self):
        self.count = self.count + 1

    def get(self):
        return self.count

    def reset(self):
        self.count = 0

counter = Counter()
counter.inc()
counter.inc()
counter.inc()
print(counter.get())   # 3

counter.reset()
print(counter.get())   # 0

Kesalahan umum.

  • Lupa self sebagai parameter pertama di setiap method. Python akan mengeluarkan TypeError yang menyatakan method menerima 0 argumen padahal 1 diberikan.
  • Menulis count = 0 di level class alih-alih self.count = 0 di dalam __init__. Variable di level class dibagi oleh semua instance, bukan disimpan per object.

Soal 2 — Anjing dengan gonggongan

Soal. Dua object Dog dengan nama masing-masing, masing-masing memanggil bark()-nya sendiri.

Cara berpikir. Setiap pemanggilan Dog(name) menciptakan object terpisah dengan self.name-nya sendiri. Kode method yang sama berjalan untuk keduanya, tapi self merujuk ke object yang berbeda setiap kali.

Solusi.

class Dog:
    def __init__(self, name):
        self.name = name

    def bark(self):
        print(f"{self.name}: Woof!")

rex = Dog("Rex")
lassie = Dog("Lassie")

rex.bark()      # Rex: Woof!
lassie.bark()   # Lassie: Woof!

Kesalahan umum.

  • Menggunakan variable global name di dalam bark alih-alih self.name. Kedua anjing akan mencetak nama yang sama.

Soal 3 — Object kalkulator

Soal. Object Calc dengan method aritmetika yang memperbarui nilai internal.

Solusi.

class Calc:
    def __init__(self):
        self.value = 0

    def add(self, n):
        self.value = self.value + n

    def sub(self, n):
        self.value = self.value - n

    def mul(self, n):
        self.value = self.value * n

    def show(self):
        print(f"Value: {self.value}")

calc = Calc()
calc.add(10)
calc.show()    # Value: 10
calc.mul(3)
calc.show()    # Value: 30
calc.sub(5)
calc.show()    # Value: 25

Kesalahan umum.

  • Mengembalikan nilai baru dari setiap method alih-alih memperbarui self.value. Keduanya tidak masalah, tapi soal meminta pembaruan di tempat.

Tantangan — Stack

Soal. Stack LIFO dengan push, pop, peek, size.

Solusi.

class Stack:
    def __init__(self):
        self.items = []

    def push(self, v):
        self.items.append(v)

    def pop(self):
        return self.items.pop()

    def peek(self):
        if len(self.items) == 0:
            return None
        return self.items[-1]

    def size(self):
        return len(self.items)

stack = Stack()
stack.push("a")
stack.push("b")
stack.push("c")
print(stack.size())    # 3
print(stack.peek())    # c
print(stack.pop())     # c
print(stack.pop())     # b
print(stack.size())    # 1

list.append() dan list.pop() tanpa index bekerja di ujung list — tempat yang tepat untuk operasi stack.

Kesalahan umum.

  • Memanggil self.items.pop(0) — itu menghapus dari depan, menjadikannya queue, bukan stack, dan lebih lambat karena setiap item lain bergeser.
  • Tidak menjaga peek — memanggil self.items[-1] pada list kosong akan memunculkan IndexError.
  • Lupa mengembalikan nilai dari pop dan peek. Default return adalah None, yang diam-diam merusak pengujian.

Selesai?

Bab berikutnya mengembangkan pola ini lebih jauh. Dengan class yang tepat, kamu berhenti menulis boilerplate __init__ untuk setiap object secara terpisah dan berbagi definisi method di banyak instance yang kamu buat dengan bersih menggunakan pemanggilan constructor.