__slots__ — bir sınıfın özel bir niteliği olup, örneğin izin verilen niteliklerin kümesini kısıtlar, bellek tasarrufu sağlar ve niteliklere erişimi hızlandırır. __slots__ kullanımı, birçok benzer nesne için özellikle geçerlidir.
Konuya giriş:
__slots__'ın ortaya çıkması, her Python nesnesinin varsayılan olarak bir nitelik sözlüğüne (__dict__) sahip olmasından kaynaklanmaktadır; bu kullanışlıdır ancak bellek açısından maliyetlidir. Küçük bir nitelik setine sahip bir milyon nesne için önemli bir ek yük meydana gelir.
Sorun:
Normal bir sınıfın örnekleri dinamik olarak genişletilebilir; bu kullanışlıdır, ancak verimsizdir. __slots__ kullanmak, yeni niteliklerin dinamik olarak eklenmesini kısıtlar, örneklik niteliğini kaldırır, bellek tasarrufu sağlar ve erişimi hızlandırır.
Çözüm:
İzin verilen alanların listesini __slots__ niteliğinde belirtin:
class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y p = Point(1, 2) p.z = 3 # AttributeError: 'Point' nesnesinin 'z' niteliği yok
Anahtar özellikler:
slots ile bir sınıf örneği oluşturmaya çalışırken liste dışı bir nitelik eklenebilir mi?
Hayır. __slots__ listesinde olmayan bir niteliği eklemeye çalıştığınızda AttributeError hatası fırlatılacaktır. Bu, nesnenin genişletilebilirliği üzerinde kısıtlamalar getirir.
slots olan bir sınıftan miras alınabilir mi ve yeni alanlar eklenebilir mi?
Evet, ancak her miras alan sınıf kendi __slots__'ını tanımlamalıdır. Bu durumda, ebeveyn ve mevcut __slots__ birleştirilir. Ancak, miras alandaki __slots__ tanımlanmazsa, çocuk nesne tekrar bir __dict__'e sahip olacaktır!
Immutable (değişmez) türler için slots çalışır mı?
Evet, ancak slot nesnesinin değişmez olmasını sağlamak için ek önlemler almak gerekir (örneğin, setter olmadan property aracılığıyla).
Bir nokta için normal sınıf:
class Point: def __init__(self, x, y): self.x = x self.y = y points = [Point(i, i) for i in range(1_000_000)]
Artıları:
Eksileri:
Benzer sınıf ancak slotlar ile:
class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y points = [Point(i, i) for i in range(1_000_000)]
Artıları:
Eksileri: