Perché non ci sono modificatori di accesso esplicito in Python:


28

Se "esplicito è meglio di implicito", perché non ci sono modificatori di accesso esplicito in Python: pubblico, protetto, privato, ecc.?

So che l'idea è che il programmatore dovrebbe sapere cosa fare attraverso un suggerimento - non c'è bisogno di usare la "forza bruta". Ma "incapsulamento" o "occultamento delle informazioni" dell'IMO non è solo per tenere fuori le persone, è una questione di organizzazione e struttura: i livelli di sviluppo dovrebbero avere ambiti e confini auto-definiti e chiaramente delimitati, proprio come fanno i sistemi fisici.

Qualcuno può aiutarmi qui con una solida spiegazione del perché le restrizioni di accesso sono implicite piuttosto che esplicite in Python, un linguaggio che altrimenti sembra vicino alla perfezione?

Modifica: Finora ho visto 3 risposte proposte e mi sono reso conto che ci sono 2 parti della mia domanda:

  1. Perché non ci sono parole chiave, per esempio

    private def myFunc(): 
        dostuff....
    

    invece di IMO i trattini bassi brutti e difficili da scrivere. Ma non è questo il punto importante.

  2. Ma ancora più importante:

    Perché questi modificatori di accesso sono solo "raccomandazioni" o suggerimenti e non applicati. Sarà difficile cambiare in seguito? È molto semplice cambiare da 'protetto' a 'pubblico' - e se si dispone di una catena di eredità contorta che lo rende difficile, si ha un design scadente - il proprio design dovrebbe essere raffinato piuttosto che basarsi su una funzionalità linguistica che lo rende facile da scrivere codice mal strutturato.

    Quando vengono applicati i modificatori di accesso, il tuo codice viene automaticamente suddiviso in compartimenti - SAPI che alcuni segmenti non rientrano nell'ambito di applicazione, quindi non devi gestirli tranne se e quando è necessario. E, se il tuo design non va bene e ti ritrovi a spostare continuamente le cose dentro e fuori da ambiti diversi, il linguaggio può aiutarti a ripulire il tuo atto.

Per quanto ami Python, trovo che questo secondo punto sia una grave carenza. E devo ancora vedere una buona risposta per questo.


possibile duplicato di identificatori di Access in Python: ... che è stato chiuso come non costruttivo.
Frank Shearar,

2
@Frank, questa è una nuova domanda di quella domanda per cercare di essere più costruttivi. Sono andato avanti e ho eliminato la domanda originale.

@Mark Trapp: Ah OK. Grazie per il chiarimento. Non riesco a vedere come annullare il mio voto per chiudere.
Frank Shearar,

@Frank Invecchierà da solo.
Adam Lear

il problema private def whateverè che si class x: def whatever(self): passtratta di una scorciatoia per class x: pass; x.whatever = lambda self: pass, quindi in pratica, per l'assegnazione sarebbe necessario un modificatore privato
keppla,

Risposte:


22

"Esplicitare è meglio che implicito" è solo una delle massime della filosofia progettuale di Python. "Semplice è meglio di complesso" c'è anche. E, sebbene non sia nello Zen di Python, "Siamo tutti adulti consenzienti qui" è un altro.

Quella seconda regola è forse la più importante qui. Quando progetto una classe, ho un'idea di come verrà utilizzata. Ma non posso prevedere tutti gli usi possibili. È possibile che un uso futuro del mio codice richieda l'accesso alle variabili che ho considerato private. Perché dovrei rendere difficile - o addirittura impossibile - accedere a questi, se un futuro programmatore (o anche un futuro me) ne ha bisogno? La cosa migliore da fare è contrassegnarli con un avvertimento - come nota Joonas, un singolo prefisso di sottolineatura è lo standard - che sono interni e potrebbero cambiare; ma vietare del tutto l'accesso non sembra necessario.


1
"Semplice è meglio di complesso" e "Siamo tutti consenzienti adulti qui" sono il motivo per cui Smalltalk non ha modificatori di accesso. Mettere un metodo nella categoria "privato" è un suggerimento che dovresti pensare tre volte prima di usarlo, e non di più.
Frank Shearar,

@Frank: "Mettere un metodo nella categoria" privata "è un suggerimento che dovresti pensare tre volte prima di usarlo, e non più" Per me, significa semplicemente che non devo preoccuparmi quando non ho a che fare con esso.
Vettore

8
C'è una buona ragione per proibire l'accesso ai membri privati: perché potrebbe spezzare gli invarianti di classe. Se non riesci a scrivere membri privati, non puoi essere sicuro che la tua classe si comporti correttamente.
svick,

7
"Perché dovrei rendere difficile - o addirittura impossibile - accedere a questi, se un futuro programmatore (o anche un futuro me) ne ha bisogno?" Perché uno dei principi di base del design è la separazione tra interfaccia (cosa fornisce un pezzo di codice) e implementazione (come lo fornisce). L'incapsulamento serve a ridurre la complessità del codice riducendo le dipendenze tra le diverse parti del codice. Pertanto, pubblico e privato vengono utilizzati esattamente allo scopo di semplificare il codice consentendo di vedere solo ciò che è necessario.
Giorgio,

3
Non posso più diagree. I modificatori di accesso promuovono due dei concetti probabilmente meglio compresi per ridurre la complessità nei grandi software: incapsulamento e separazione delle preoccupazioni. Non riuscire a servire nessuno dei due significa semplicemente che Python non è un buon linguaggio OOP né adatto alla costruzione di software di grandi dimensioni e non c'è nulla di sbagliato in questo. Ma giustificare l'assenza di tali caratteristiche con argomenti tipici dell'hobbista come "Perché aggiungere complessità quando non è necessario?" è solo sbagliato.
Daniel Shin,

10

Sospetto che il motivo principale per cui i modificatori di accesso mancanti sono Semplicità

Come dici tu, non si tratta di tenere le persone fuori, si tratta di organizzazione, quindi il punto principale di "privato" è che invia un messaggio agli utenti della tua API "per favore non scrivere codice che dipende da questo".

È banale dire 'per convenzione, _x o __x non dovrebbero essere usati al di fuori della classe', ma nel modello a oggetti dinamici di Python, sarebbe difficile persino trovare una notazione.

class ActiveRow(object):
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)

come notare l'accessibilità?

Immagino che questo fosse un compromesso. Se non puoi assolutamente conviverci, suggerirei ruby, che ha un livello simile di astrazione e dinamicità, ma ha un modello a oggetti, che consente la modifica dell'accesso.


8
Penso che sia corretto, ma IMO, è terribile. Per un linguaggio che utilizza l'eleganza e la leggibilità come punti di forza, la scrittura di __method__ è piuttosto noiosa e ottusa.
jiggy,

2
questa non è la convenzione, __x__sono "magici" (ovvero metodi che vengono chiamati per consentire l'integrazione del linguaggio come sovraccarico dell'operatore, iterabilità, ecc.). La convenzione è _x.
keppla,

6
Mi dispiace, mi sto ancora concentrando su Python. Sto provando così tanto a piacermi, ma cose come questa fanno impazzire. Soprattutto ora che devo ricordare il significato di quanti caratteri di sottolineatura ha un metodo. Al punto di OP, sembra che i modificatori espliciti sarebbero più chiari. La concisione è fantastica, ma non può superare la chiarezza. Impieghi 10 volte di più per mantenere il codice che per costruirlo.
jiggy,

2
Il mio esempio non intendeva mostrare diversi conteggi di sottolineatura, l'uso di __init__era accidentale. L'esempio imposta alcune proprietà dell'oggetto, che non sono note al momento della compilazione, quindi un modificatore di accesso esplicito non ti aiuterebbe.
keppla,

5
@jiggy: "Sto provando così tanto a farmi piacere". Ho provato per 2 anni - poi ho rinunciato. :-( Sembra essere un linguaggio di scripting che è stato violato per comportarsi in qualche modo come un vero linguaggio OOP. Non riesco a immaginare di scrivere un'app complessa e complessa in Python che sia stata ben progettata e leggibile. Come hai detto 'Spendi 10 volte di più mantenere il codice piuttosto che costruirlo ". OOP semplici e concetti sicuri di tipo richiedono hack e soluzioni alternative folli
Vector

8

La convenzione Python prevede l'uso di un prefisso di sottolineatura per i membri protetti / privati.

Questa convenzione, quando seguita, è effettivamente uguale ai modificatori di accesso, tranne 1) vedrai direttamente dal nome del membro se è pubblico o meno, e 2) puoi interrompere "incapsulamento" se lo desideri (questo può essere giustificabile ad es. test; in alcune altre lingue dovresti usare reflection == altro codice).

Alla fine è una questione di gusti, ma se puoi fare la stessa cosa (con un po 'più di flessibilità) senza parole chiave speciali, la lingua sarà più piccola e il codice sarà più conciso, il che è generalmente una buona cosa.


2
"se riesci a fare la stessa cosa (con un po 'più di flessibilità) senza parole chiave speciali, la lingua sarà più piccola e il codice sarà più conciso" Secondo me, questo non è generalmente vero. (Anche se può essere vero con il caso speciale dei modificatori di accesso)
BenjaminB,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.