2.21. Metode dan atribut

Metode adalah fungsi yang didefinisikan di dalam kelas. Parameter pertama adalah instans tempat metode dipanggil; konvensionalnya diberi nama self.

2.21.1. Metode instans

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def magnitude(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5

p = Point(3, 4)
print(p.magnitude())

Output:

5.0

Panggilan p.magnitude() meneruskan p sebagai self secara otomatis. Badan metode membaca dan memperbarui atribut melalui self dengan cara yang sama fungsi membaca dan memperbarui nama melalui parameter.

2.21.2. Atribut instans vs kelas

Atribut yang ditugaskan ke self -- biasanya di dalam __init__ -- milik instans tersebut saja:

a = Point(1, 2)
b = Point(10, 20)
a.x = 99
print(a.x, b.x)           # 99 10

a.x dan b.x adalah penyimpanan yang berbeda; mengubah satu tidak mempengaruhi yang lain.

Nama yang ditugaskan di badan kelas, di luar metode apa pun, dibagikan oleh setiap instans kelas:

class Counter:
    kind = "tally"        # class attribute -- shared

    def __init__(self):
        self.value = 0    # instance attribute -- per instance

a = Counter()
b = Counter()
print(a.kind, b.kind)     # tally tally
A class block at the top holding shared methods and the class attribute "kind"; below it, two instance boxes each holding their own "value" attribute, with arrows from each instance up to the class.

Atribut kelas berada di kelas itu sendiri dan dibagikan. Atribut instans berada di setiap instans.

Atribut kelas dicapai dengan cara yang sama seperti atribut instans (a.kind); Python pertama-tama mencari di instans, kemudian di kelas. Menetapkan ke a.kind akan membuat atribut instans baru yang menutupi atribut kelas, membiarkan b.kind tidak tersentuh.

Gunakan atribut kelas untuk konstanta dan default yang setiap instans harus lihat dengan cara yang sama. Gunakan atribut instans untuk status yang setiap objek harus memiliki salinannya sendiri.

2.21.3. __str__ dan __repr__

Dua metode khusus mengontrol cara instans dicetak. __str__ mengembalikan string "ramah" yang digunakan oleh print(); __repr__ mengembalikan string "pengembang" yang digunakan di REPL dan di dalam tampilan wadah:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return "(" + str(self.x) + ", " + str(self.y) + ")"

    def __repr__(self):
        return "Point(" + str(self.x) + ", " + str(self.y) + ")"

p = Point(3, 4)
print(p)            # uses __str__
print([p, p])       # uses __repr__ inside the list

Output:

(3, 4)
[Point(3, 4), Point(3, 4)]

Jika hanya __repr__ yang didefinisikan, print() akan kembali ke sana -- jadi __repr__ yang ditulis dengan baik biasanya sudah cukup. Definisikan __str__ juga hanya ketika bentuk ramah harus terlihat berbeda dari bentuk pengembang. Usahakan membuat __repr__ yang terlihat seperti panggilan yang akan membuat ulang objek; proses debug menjadi jauh lebih mudah ketika nilai yang dicetak tidak ambigu.