2.21. Yöntemler ve nitelikler

Yöntem, bir sınıfın içinde tanımlanan bir fonksiyondur. İlk parametre, yöntemin üzerinde çağrıldığı örnektir; geleneksel olarak ona self adı verilir.

2.21.1. Örnek yöntemleri

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())

Çıktı:

5.0

p.magnitude() çağrısı p öğesini otomatik olarak self olarak geçirir. Yöntem gövdeleri, fonksiyonların parametreler aracılığıyla adları okuyup güncellemesi gibi, nitelikleri self aracılığıyla okuyup günceller.

2.21.2. Örnek nitelikleri ile sınıf nitelikleri

self‘e atanan nitelikler – tipik olarak __init__ içinde – yalnızca o örneğe aittir:

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

a.x ve b.x farklı depolama alanlarıdır; birini değiştirmek diğerini etkilemez.

Sınıf gövdesinde, herhangi bir yöntemin dışında atanan adlar, sınıfın her örneği tarafından paylaşılır:

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
Üstte paylaşılan yöntemleri ve "kind" sınıf niteliğini tutan bir sınıf bloğu; altında, her biri kendi "value" niteliğini tutan iki örnek kutusu ve her örnekten yukarıya sınıfa doğru oklar.

Sınıf nitelikleri sınıfın kendisinde yaşar ve paylaşılır. Örnek nitelikleri her örnekte yaşar.

Bir sınıf niteliğine, bir örnek niteliğiyle aynı şekilde erişilir (a.kind); Python önce örneğe, sonra sınıfa bakar. a.kind öğesine atama yapmak, sınıf olanını gölgeleyen yeni bir örnek niteliği oluşturur ve b.kind öğesine dokunmaz.

Her örneğin aynı şekilde görmesi gereken sabitler ve varsayılanlar için sınıf niteliklerini kullanın. Her nesnenin kendi kopyasına sahip olması gereken durum için örnek niteliklerini kullanın.

2.21.3. __str__ ve __repr__

İki özel yöntem, bir örneğin nasıl yazdırılacağını denetler. __str__, print() tarafından kullanılan “dostça” dizeyi döndürür; __repr__, REPL’de ve kapsayıcı görünümlerinin içinde kullanılan “geliştirici” dizeyi döndürür:

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

Çıktı:

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

Yalnızca __repr__ tanımlanmışsa, print() ona geri döner – bu nedenle iyi yazılmış tek bir __repr__ genellikle yeterlidir. Dostça biçimin geliştirici biçiminden farklı görünmesi gerektiğinde __str__ öğesini de tanımlayın. Nesneyi yeniden oluşturacak çağrıya benzeyen bir __repr__ hedefleyin; yazdırılan değerler belirsiz olmadığında hata ayıklama büyük ölçüde kolaylaşır.