Domanda

Come posso rendere privati ​​metodi e membri dati in Python?Oppure Python non supporta i membri privati?

È stato utile?

Soluzione

9.6.Variabili private

Le variabili di istanza "privata" a cui non è possibile accedere, tranne dall'interno di un oggetto, non esistono in Python.Tuttavia, c'è una convenzione seguita dalla maggior parte del codice Python:Un nome prefisso con un sottolineaggio (ad es._SPAM) dovrebbe essere trattato come una parte non pubblica dell'API (che si tratti di una funzione, un metodo o un membro dei dati).Dovrebbe essere considerato un dettaglio di implementazione e soggetto a modifiche senza preavviso.

Poiché esiste un caso d'uso valido per i membri della classe-privata (vale a dire per evitare scontri di nomi con nomi definiti dalle sottoclassi), esiste un supporto limitato per tale meccanismo, chiamato manglistica.Qualsiasi identificatore del modulo __SPAM (almeno due principali punteggi, al massimo un sottolineaggio tradotto) viene sostituito testualmente _classname__spam, dove ClassName è il nome di classe corrente con le principali sottolineature ridotte.Questo muscolo viene fatto senza riguardo alla posizione sintattica dell'identificatore, purché si verifichi all'interno della definizione di classe.

COSÌ, Per esempio,

class Test:
    def __private_symbol(self):
        pass
    def normal_symbol(self):
        pass

print dir(Test)

restituirà:

['_Test__private_symbol', 
'__doc__', 
'__module__', 
'normal_symbol']

__private_symbol dovrebbe essere considerato un metodo privato, ma sarebbe comunque accessibile tramite _Test__private_symbol.

Altri suggerimenti

Le altre risposte forniscono i dettagli tecnici.Vorrei sottolineare la differenza filosofica tra Python da un lato e linguaggi come C++/Java (che presumo tu abbia familiarità in base alla tua domanda).

L'atteggiamento generale in Python (e Perl del resto) è che la 'privacy' di un attributo è una richiesta al programmatore piuttosto che un recinto di filo spinato da parte del compilatore/interprete.L'idea è ben sintetizzata questa posta ed è spesso definito come "Siamo tutti adulti consenzienti" poiché "presuppone" che il programmatore sia sufficientemente responsabile da non immischiarsi con gli interni.I caratteri di sottolineatura iniziali servono come messaggio educato per indicare che l'attributo è interno.

D'altra parte, se tu Fare vuoi accedere agli interni di alcune applicazioni (un esempio notevole sono i generatori di documentazione come pydoc), sei libero di farlo.Spetta a te come programmatore sapere cosa stai facendo e farlo correttamente piuttosto che al linguaggio per costringerti a fare le cose suo modo.

Non ci sono private di qualsiasi altro meccanismo di protezione dell'accesso in Python.Esiste una convenzione documentata nel Guida allo stile Python per indicare agli utenti della tua classe che non dovrebbero accedere a determinati attributi.

  • _singolo_tratto_sottolineato_iniziale:debole indicatore di “uso interno”.Per esempio. from M import * non importa oggetti il ​​cui nome inizia con un carattere di sottolineatura.

  • single_trailing_underscore_:utilizzato per convenzione per evitare conflitti con le parole chiave Python, ad es. Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore:quando si nomina un attributo di classe, invoca la modifica del nome (all'interno della classe FooBar, __boo diventa _FooBar__boo;vedi sotto).

Se il nome di una funzione Python, metodo di classe o attributo inizia con (ma non finisce con) due sottoti, è privato; Tutto il resto è pubblico.Python non ha alcun concetto di metodi di classe protetta (accessibile solo nelle loro classi e classi discendenti).I metodi di classe sono privati ​​(accessibili solo nella propria classe) o pubblici (accessibili da qualsiasi luogo).

Immergiti in Python

Python non supporta direttamente la privacy.Il programmatore deve sapere quando è sicuro modificare l'attributo dall'esterno, ma comunque con Python puoi ottenere qualcosa di simile al privato con piccoli trucchi.Ora vediamo che una persona può inserire o meno qualcosa di privato.

class Person(object):

    def __priva(self):
        print "I am Private"

    def publ(self):
        print " I am public"

    def callpriva(self):
        self.__priva()

Ora quando eseguiremo:

>>> p = Person()
>>> p.publ()
 I am public
>>> p.__priva()
Traceback (most recent call last):
  File "", line 1, in 
    p.__priva()
AttributeError: 'Person' object has no attribute '__priva'
​#Explanation   : You can see  here we are not able to fetch that private method directly.
>>> p.callpriva()
I am Private
#​Explanation  : Here we can access private method inside class​

​Allora come qualcuno può accedere a quella variabile ???
Puoi fare come:

>>>p._Person__priva
I am Private

​wow, in realtà se Python riceve qualsiasi variabile che inizia con un doppio carattere di sottolineatura viene "tradotta" aggiungendo un singolo carattere di sottolineatura e il nome della classe all'inizio:

Nota : Se non vuoi che questo nome cambi ma vuoi comunque inviare un segnale affinché altri oggetti stiano lontani, puoi utilizzare un singolo carattere di sottolineatura iniziale i nomi con un carattere di sottolineatura iniziale non vengono importati con le importazioni con asterisco (dall'importazione del modulo *)
Esempio :

#test.py
def hello():
    print "hello"
def _hello():
    print "Hello private"

#----------------------
#test2.py
from test import *
print hello()
print _hello()

uscita-->

hello
Traceback (most recent call last):
  File "", line 1, in 
NameError: name '_hello' is not defined

Ora se chiameremo _hello manualmente.

#test2.py
from test import _hello , hello
print hello()
print _hello()

uscita-->

hello
hello private

Finalmente :Python non ha davvero un supporto per la privacy equivalente, sebbene in una certa misura ti danno in una certa misura un singolo e doppio

Questo potrebbe funzionare:

import sys, functools

def private(member):
    @functools.wraps(member)
    def wrapper(*function_args):
      myself = member.__name__
      caller = sys._getframe(1).f_code.co_name
      if (not caller in dir(function_args[0]) and not caller is myself):
         raise Exception("%s called by %s is private"%(myself,caller))
      return member(*function_args)
    return wrapper

class test:
   def public_method(self):
      print('public method called')

   @private
   def private_method(self):
      print('private method called')

t = test()
t.public_method()
t.private_method()

Questa è una risposta piuttosto lunga, ma penso che arrivi alla radice del vero problema qui: l'ambito della visibilità.Resisti mentre mi affretto a risolvere questo problema!

La semplice importazione di un modulo non deve necessariamente fornire allo sviluppatore dell'applicazione l'accesso a tutte le sue classi o metodi;se non riesco effettivamente a VEDERE il codice sorgente del modulo come faccio a sapere cosa è disponibile?Qualcuno (o qualche COSA) deve dirmi cosa posso fare e spiegarmi come utilizzare quelle funzionalità che mi è consentito utilizzare, altrimenti per me è tutto inutile.

A coloro che sviluppano astrazioni di livello superiore basate su classi e metodi fondamentali tramite moduli importati viene presentato un DOCUMENTO di specifica, NON il codice sorgente effettivo.

Le specifiche del modulo descrivono tutte le funzionalità destinate ad essere visibili allo sviluppatore del client.Quando si ha a che fare con progetti di grandi dimensioni e team di progetto software, l'effettiva implementazione di un modulo dovrebbe SEMPRE rimanere nascosta a coloro che lo utilizzano: è una scatola nera con un'interfaccia verso il mondo esterno.Per i puristi dell'OOD, credo che i termini tecnici siano "disaccoppiamento" e "coerenza".L'utente del modulo deve solo conoscere i metodi di interfaccia senza essere gravato dai dettagli dell'implementazione.

Un modulo non dovrebbe MAI essere modificato senza prima modificare il documento delle specifiche sottostanti, che potrebbe richiedere revisione/approvazione in alcune organizzazioni prima di modificare il codice.

Come programmatore per hobby (ora in pensione), inizio un nuovo modulo con il documento delle specifiche effettivamente scritto come un gigantesco blocco di commenti nella parte superiore del modulo, questa sarà la parte che l'utente vedrà effettivamente nella libreria delle specifiche.Dato che sono solo io, devo ancora creare una libreria, ma sarebbe abbastanza facile da fare.

Quindi inizio a scrivere il codice scrivendo le varie classi e metodi ma senza corpi funzionali - solo istruzioni di stampa nulle come "print()" - quanto basta per consentire la compilazione del modulo senza errori di sintassi.Una volta completato questo passaggio, compilo il modulo null completato: queste sono le mie specifiche.Se lavorassi in un team di progetto, presenterei queste specifiche/interfaccia per la revisione e i commenti prima di procedere con la realizzazione del corpo.

Ho arricchito i corpi di ciascun metodo uno alla volta e compilato di conseguenza, garantendo che gli errori di sintassi vengano corretti immediatamente al volo.Questo è anche un buon momento per iniziare a scrivere una sezione di esecuzione "principale" temporanea in basso per testare ciascun metodo mentre lo codifichi.Una volta completati la codifica/il test, tutto il codice del test viene commentato fino a quando non sarà nuovamente necessario qualora si rendessero necessari aggiornamenti.

In un team di sviluppo reale, il blocco dei commenti alle specifiche apparirebbe anche in una libreria di controllo documenti, ma questa è un'altra storia.Il punto è:tu, come client del modulo, vedi solo queste specifiche e NON il codice sorgente.

PS:molto prima dell'inizio dei tempi, ho lavorato nella comunità aerospaziale della difesa e abbiamo fatto cose piuttosto interessanti, ma cose come algoritmi proprietari e logica di controllo dei sistemi sensibili erano strettamente custoditi e crittografati in librerie software super-duper sicure.Avevamo accesso alle interfacce dei moduli/pacchetti ma NON agli enti di implementazione della scatola nera.C'era uno strumento di gestione dei documenti che gestiva tutti i progetti a livello di sistema, le specifiche del software, il codice sorgente e i record dei test: era tutto sincronizzato insieme.Il governo aveva requisiti rigorosi e standard di garanzia della qualità del software.Qualcuno ricorda una lingua chiamata "Ada"?Ecco quanti anni ho!

Utilizzo Python 2.7 e 3.5.Ho scritto questo codice:

class MyOBject(object):
    def __init__(self):
        self.__private_field = 10


my_object = MyOBject()
print(my_object.__private_field)

l'ho eseguito e ho ottenuto:

Errore attributo:L'oggetto 'MyOBject' non ha l'attributo '__private_field'

Perfavore guarda:https://www.tutorialsteacher.com/python/private-and-protected-access-modifiers-in-python

Se si desidera creare un metodo o membri di dati privati ​​in Python, usa __setattr __

class Number:
    def __init__(self,value):
        self.my_private = value

    def __setattr__(self, my_private, value):
        # the default behavior
        # self.__dict__[my_private] = value
        raise Exception("can't access private member-my_private")


def main():
    n = Number(2)
    print(n.my_private)

if __name__ == '__main__': 
    main()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top