In caso di dubbio, lascialo "pubblico" - Voglio dire, non aggiungere nulla per oscurare il nome del tuo attributo. Se hai una classe con qualche valore interno, non preoccupartene. Invece di scrivere:
class Stack(object):
def __init__(self):
self.__storage = [] # Too uptight
def push(self, value):
self.__storage.append(value)
scrivi questo per impostazione predefinita:
class Stack(object):
def __init__(self):
self.storage = [] # No mangling
def push(self, value):
self.storage.append(value)
Questo è sicuramente un modo controverso di fare le cose. I neofiti di Python lo odiano e anche alcuni vecchi ragazzi di Python disprezzano questa impostazione predefinita, ma è comunque l'impostazione predefinita, quindi ti consiglio davvero di seguirla, anche se ti senti a disagio.
Se vuoi davvero inviare il messaggio "Non posso toccarlo!" per i tuoi utenti, il modo usuale è far precedere la variabile con un trattino basso. Questa è solo una convenzione, ma le persone la capiscono e si prendono una doppia cura quando si tratta di cose del genere:
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)
Questo può essere utile anche per evitare conflitti tra nomi di proprietà e nomi di attributi:
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
E il doppio trattino basso? Ebbene, la magia del doppio trattino basso viene utilizzata principalmente per evitare il sovraccarico accidentale dei metodi e conflitti di nome con gli attributi delle superclassi . Può essere molto utile se scrivi una classe che dovrebbe essere estesa molte volte.
Se vuoi usarlo per altri scopi, puoi, ma non è né usuale né consigliato.
EDIT : Perché è così? Bene, il solito stile Python non enfatizza il fatto di rendere le cose private, al contrario! Ci sono molte ragioni per questo - la maggior parte controversa ... Vediamone alcune.
Python ha proprietà
La maggior parte delle lingue OO oggi usa l'approccio opposto: ciò che non dovrebbe essere usato non dovrebbe essere visibile, quindi gli attributi dovrebbero essere privati. Teoricamente, ciò produrrebbe classi più gestibili e meno accoppiate, perché nessuno cambierebbe i valori all'interno degli oggetti in modo sconsiderato.
Tuttavia, non è così semplice. Ad esempio, le classi Java hanno molti attributi e getter che ottengono solo i valori e setter che impostano semplicemente i valori. Sono necessarie, diciamo, sette righe di codice per dichiarare un singolo attributo, che un programmatore Python direbbe che è inutilmente complesso. Inoltre, in pratica, devi solo scrivere tutto questo codice per ottenere un campo pubblico, poiché puoi modificarne il valore usando getter e setter.
Allora perché seguire questa politica privata per impostazione predefinita? Rendi pubblici i tuoi attributi per impostazione predefinita. Ovviamente, questo è problematico in Java, perché se decidi di aggiungere una convalida al tuo attributo, ti richiederebbe di cambiare tutto
person.age = age;
nel tuo codice per, diciamo,
person.setAge(age);
setAge()
essere:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
this.age = 0;
}
}
Quindi in Java (e in altri linguaggi) l'impostazione predefinita è usare comunque getter e setter, perché possono essere fastidiosi da scrivere ma possono farti risparmiare molto tempo se ti trovi nella situazione che ho descritto.
Tuttavia, non è necessario farlo in Python, poiché Python ha proprietà. Se hai questa classe:
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
e poi decidi di convalidare le età, non è necessario modificare i person.age = age
pezzi del tuo codice. Basta aggiungere una proprietà (come mostrato di seguito)
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
Se puoi farlo e continuare a usarlo person.age = age
, perché dovresti aggiungere campi privati e getter e setter?
(Inoltre, vedere Python non è Java e questo articolo sui danni derivanti dall'uso di getter e setter .).
Tutto è comunque visibile e cercare di nascondersi complica il tuo lavoro
Anche nelle lingue in cui sono presenti attributi privati, è possibile accedervi tramite una sorta di libreria di riflessione / introspezione. E le persone lo fanno molto, in quadri e per risolvere bisogni urgenti. Il problema è che le librerie di introspezione sono solo un modo difficile per fare ciò che potresti fare con gli attributi pubblici.
Poiché Python è un linguaggio molto dinamico, è semplicemente controproducente aggiungere questo peso alle tue classi.
Il problema non è essere possibile vedere, è necessario vedere
Per un Pythonista, l'incapsulamento non è l'incapacità di vedere l'interno delle classi, ma la possibilità di evitare di guardarlo. Quello che voglio dire è che l'incapsulamento è la proprietà di un componente che ne consente l'utilizzo senza che l'utente si preoccupi dei dettagli interni. Se puoi usare un componente senza preoccuparti della sua implementazione, allora è incapsulato (secondo l'opinione di un programmatore Python).
Ora, se hai scritto la tua classe in questo modo puoi usarla senza dover pensare ai dettagli di implementazione, non ci sono problemi se vuoi guardare dentro la classe per qualche motivo. Il punto è: la tua API dovrebbe essere buona e il resto sono dettagli.
L'ha detto Guido
Ebbene, questo non è controverso: lo ha detto, in realtà . (Cerca "kimono aperto".)
Questa è cultura
Sì, ci sono alcune ragioni, ma nessuna ragione critica. Questo è principalmente un aspetto culturale della programmazione in Python. Francamente, potrebbe essere anche il contrario, ma non lo è. Inoltre, potresti facilmente chiedere il contrario: perché alcune lingue utilizzano attributi privati per impostazione predefinita? Per lo stesso motivo principale della pratica Python: perché è la cultura di questi linguaggi, e ogni scelta ha vantaggi e svantaggi.
Poiché esiste già questa cultura, ti consigliamo di seguirla. Altrimenti, sarai infastidito dai programmatori Python che ti dicono di rimuovere __
dal codice quando fai una domanda in Stack Overflow :)