Şüpheye düştüğünüzde, "herkese açık" bırakın - Demek istediğim, niteliğinizin adını gizlemek için hiçbir şey eklemeyin. İçsel değeri olan bir sınıfınız varsa, onun için endişelenmeyin. Yazmak yerine:
class Stack(object):
def __init__(self):
self.__storage = [] # Too uptight
def push(self, value):
self.__storage.append(value)
bunu varsayılan olarak yazın:
class Stack(object):
def __init__(self):
self.storage = [] # No mangling
def push(self, value):
self.storage.append(value)
Bu kesinlikle bir şeyler yapmanın tartışmalı bir yoludur. Python'a yeni başlayanlar bundan nefret ediyor ve hatta bazı eski Python adamları bile bu varsayılanı küçümsüyor - ama yine de varsayılandır, bu yüzden rahatsız hissetseniz bile onu takip etmenizi gerçekten tavsiye ederim.
Eğer varsa gerçekten mesaj göndermek istiyorum "Dokunamazsın!" Kullanıcılarınız için olağan yöntem, değişkenin önüne bir alt çizgi koymaktır. Bu sadece bir sözleşmedir, ancak insanlar bunu anlar ve bu tür şeylerle uğraşırken çok dikkatli olurlar:
class Stack(object):
def __init__(self):
self._storage = [] # This is ok but pythonistas use it to be relaxed about it
def push(self, value):
self._storage.append(value)
Bu, özellik adları ile öznitelik adları arasındaki çakışmayı önlemek için de yararlı olabilir:
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
Çift alt çizgi ne olacak? Çift alt çizgi sihri, esas olarak yöntemlerin yanlışlıkla aşırı yüklenmesini önlemek ve üst sınıfların nitelikleriyle ad çatışmalarını önlemek için kullanılır . Birçok kez uzatılması beklenen bir sınıf yazarsanız oldukça faydalı olabilir.
Başka amaçlar için kullanmak isterseniz, yapabilirsiniz, ancak bu ne normaldir ne de tavsiye edilir.
DÜZENLEME : Bu neden böyle? Normal Python stili, işleri özel kılmayı vurgulamıyor - tam tersine! Bunun pek çok nedeni var - çoğu tartışmalı ... Bazılarına bakalım.
Python'un özellikleri vardır
Günümüzde çoğu OO dili zıt yaklaşımı kullanmaktadır: kullanılmaması gerekenler görünür olmamalıdır, bu nedenle öznitelikler özel olmalıdır. Teorik olarak, bu daha yönetilebilir, daha az bağlantılı sınıflar sağlar, çünkü kimse nesnelerin içindeki değerleri pervasızca değiştirmez.
Ancak o kadar basit değil. Örneğin, Java sınıfları bir çok özelliklerini var ve sadece alıcılar almak değerleri ve sadece ayarlayıcıları set değerleri. Diyelim ki tek bir özniteliği bildirmek için yedi satırlık koda ihtiyacınız var - ki bir Python programcısı gereksiz yere karmaşık olduğunu söyler. Ayrıca, pratikte, bir genel alan elde etmek için bu kadar çok kod yazarsınız, çünkü alıcıları ve ayarlayıcıları kullanarak değerini değiştirebilirsiniz.
Öyleyse neden bu varsayılan olarak özel politikayı takip etmelisiniz? Özniteliklerinizi varsayılan olarak herkese açık hale getirin. Elbette, bu Java'da sorunludur, çünkü özniteliğinize bazı doğrulama eklemeye karar verirseniz, hepsini değiştirmeniz gerekir.
person.age = age;
kodunuzda, diyelim ki
person.setAge(age);
setAge()
olmak:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
this.age = 0;
}
}
Yani Java'da (ve diğer dillerde), varsayılan olan, yine de alıcıları ve ayarlayıcıları kullanmaktır, çünkü yazmak için can sıkıcı olabilir, ancak kendinizi anlattığım durumda bulursanız size çok zaman ayırabilir.
Ancak, Python'un özellikleri olduğu için bunu Python'da yapmanıza gerek yoktur. Bu sınıfa sahipseniz:
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
ve sonra yaşları doğrulamaya karar verirseniz person.age = age
, kodunuzun parçalarını değiştirmenize gerek kalmaz . Bir mülk eklemeniz yeterlidir (aşağıda gösterildiği gibi)
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
Yapabiliyorsanız ve yine de kullanabiliyorsanız person.age = age
, neden özel alanlar, alıcılar ve ayarlayıcılar eklemelisiniz?
(Ayrıca, Python Java değildir ve alıcı ve ayarlayıcı kullanmanın zararları hakkındaki bu makaleye bakın .).
Her şey zaten görünür - ve saklamaya çalışmak sadece işinizi zorlaştırır
Özel niteliklerin olduğu dillerde bile, onlara bir tür yansıma / iç gözlem kitaplığı aracılığıyla erişebilirsiniz. Ve insanlar bunu çerçeveler içinde ve acil ihtiyaçları çözmek için çok yapıyor. Sorun, iç gözlem kitaplıklarının, genel niteliklerle yapabileceklerinizi yapmanın sadece zor bir yolu olmasıdır.
Python çok dinamik bir dil olduğundan, bu yükü sınıflarınıza eklemek ters etki yaratır.
Sorun görmek mümkün olmak değildir - ediliyor gerekli görmek için
Bir Pythonista için kapsülleme, sınıfların içlerini görme yetersizliği değil, ona bakmaktan kaçınma olasılığıdır. Demek istediğim, kapsülleme, kullanıcının dahili ayrıntılarla ilgilenmeden kullanılmasına izin veren bir bileşenin özelliğidir. Bir bileşeni, uygulama konusunda kendinizi rahatsız etmeden kullanabiliyorsanız, kapsüllenir (bir Python programcısının görüşüne göre).
Şimdi, sınıfınızı bu şekilde yazdıysanız, uygulama detaylarını düşünmek zorunda kalmadan kullanabiliyorsanız, herhangi bir sebepten dolayı sınıfın içine bakmak isterseniz sorun yok . Önemli olan şu: API'niz iyi olmalı ve gerisi ayrıntılar.
Guido öyle dedi
Bu tartışmalı değil: aslında öyle dedi . ("Açık kimono" yu arayın.)
Bu kültür
Evet, bazı nedenler var, ancak kritik bir neden yok. Bu çoğunlukla Python'da programlamanın kültürel bir yönüdür. Açıkçası, başka bir yol da olabilir - ama öyle değil. Ayrıca, bunun tersini de kolayca sorabilirsiniz: Neden bazı diller varsayılan olarak özel öznitelikleri kullanıyor? Python uygulamasıyla aynı ana nedenden ötürü: çünkü bu, bu dillerin kültürüdür ve her seçimin avantajları ve dezavantajları vardır.
Zaten bu kültür var olduğu için, onu takip etmeniz tavsiye edilir. Aksi takdirde, __
Stack Overflow'da bir soru sorduğunuzda Python programcılarının size kodu kodunuzdan kaldırmanızı söylemesinden rahatsız olacaksınız :)