Un metodo che deve essere ignorato può essere considerato privato?

5

Supponiamo di avere una classe C con un metodo f() che deve essere utilizzato solo all'interno dell'implementazione di C , ma che deve essere sovrascritto dalle sottoclassi di C .

È ragionevole, o "pythonic", considerarlo privato, cioè chiamarlo _f() piuttosto che f() ?

In altre parole, distinguere l'interfaccia fornita alle sottoclassi dall'interfaccia fornita al codice al di fuori della gerarchia dell'ereditarietà?

    
posta Nicola Musatti 25.08.2013 - 17:12
fonte

4 risposte

4

In termini pitonici, dovresti utilizzare il modulo Classe Base astratta per implementare questa funzionalità.

Esempio:

from abc import ABCMeta, abstractmethod

class MyBaseClass(object):

    __metaclass__ = ABCMeta

    @abstractmethod
    def f(self, *args):
        #"Public" method (accessible from outside of class instance)
        pass


    @abstractmethod
    def _f(self, *args):
        #"Private" method (should only be accessed from with instance)
        pass

Quindi questo è ciò che accade quando tenti di creare un'istanza di una sottoclasse di MyBaseClass senza sovrascrivere _f() :

>>> my_base_class = MyBaseClass()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MyBaseClass with abstract methods _f
>>> class B(MyBaseClass):
...     pass
... 
>>> b = B()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class B with abstract methods _f
>>> class B(MyBaseClass):
...     def _f(self):
...             print "foo"
... 
>>> b=B()
>>> b._f()
foo
>>> 

Si noti che non esistono metodi "privati" programmaticamente in Python. Detto questo, viene utilizzato un singolo carattere di sottolineatura prima del nome ( _f() ) per indicare che il metodo deve essere solo acceduto internamente.

    
risposta data 25.08.2013 - 21:10
fonte
3

La tua domanda non è propriamente specifica per Python ma potrebbe essere applicata a molti linguaggi OO come C ++ o C #. Non mi sono ancora imbattuto in una dura regola, ma lo stesso pensiero mi è venuto in mente di tanto in tanto.

Quindi ciò che segue è la mia opinione:

  • Metodo privato - ciò che solo la classe C dovrebbe conoscere e / o utilizzare. Nessun altro
  • Metodi protetti: ciò che le nuove classi dovrebbero conoscere e / o usare.
  • Metodi pubblici: quale codice esterno dovrebbe conoscere e / o utilizzare.

Quindi nel tuo esempio, renderei la funzione protetta, ma nella documentazione della classe C è molto esplicito che le classi derivate non siano destinate a chiamare direttamente questa funzione. Piuttosto, dovrebbero implementarlo e lasciare che la classe base decida quando è appropriato chiamarlo.

In altre parole, ci si aspetta che la classe derivante fornisca implementazione. Quindi, a questo punto, nulla sta fermando la persona che codifica quella classe dal chiamare quel codice. Anche se in qualche modo riesci a "contrassegnarlo come privato", dato che quella persona ha scritto quel codice una volta, lo scriverà di nuovo o troverà un altro modo per eseguirlo se è quello che lui / lei vuole veramente fare.

Per quanto riguarda ciò che è pythonic. Non sono un esperto di pitone, ma credo che questa sia la convenzione linguistica:

  • nessun prefisso di sottolineatura (ad es. f ()) = funzione pubblica
  • double underscore (cioè __f ()) = funzione privata
  • single underscore (cioè _f ()) = funzione di uso interno

Python fa molto affidamento sulla convenzione piuttosto che sul linguaggio per impedire alle persone di accedere a date private. Nulla è veramente nascosto, ma quando si prefissa il nome della funzione con "__", l'interpretazione "mangerà" quel nome di funzione. La ragione è che scoraggia (non impedisce) alle persone di scrivere codice client che chiama funzioni private:

c = C()
c.__foo()

... risulterà nell'interprete che ti dice che la funzione non esiste. Ma se qualcuno vuole davvero chiamare la tua funzione privata, scriverà semplicemente:

c._C__foo()      # mangled name (I don't remember exact
                 # naming rules, but point is the same)

Non raccomanderei l'uso di funzioni private in python per quelle protette. Sembra che il linguaggio sia realmente inteso "__" a segnalare al mondo esterno, comprese le classi derivate, "non toccare".

Nel tuo caso, userei il singolo "_" per segnalare che la funzione non è per il consumo pubblico / esterno ma piuttosto dovrebbe essere usata, o sovrascritta da qualcuno che ha abbastanza conoscenza della classe (cioè presumibilmente implementatore del la classe derivante è più ben informata su alcuni dettagli interni di qualcuno che scrive codice client).

Poche fonti che menzionano l'uso di "__" (double-underscore) per i simboli privati:

risposta data 25.08.2013 - 18:53
fonte
1

Poiché la tua domanda riguarda il modo "pitonico", vedi la sezione di denominazione di Code Like a Pythonista in cui l'autore dice "Ma cerca di evitare la forma __private.Non lo uso mai". e ancora più importante:

It's better to use the single-leading-underscore convention, _internal.  This isn't name mangled at all; it just indicates to others to "be careful with this, it's an internal implementation detail; don't touch it if you don't fully understand it". It's only a convention though.

In altre parole, il concetto stesso di "privato" non è pitonico. Inoltre, la notazione single sottolineatura _internal è esplicitamente lì per la struttura interna a scopo speciale che descrivi.

    
risposta data 26.08.2013 - 05:21
fonte
0

Non posso parlare per il modo "pythonic", dato che non ho familiarità con Python.

In linguaggi come C ++, C # e Java, esiste una disposizione esplicita per distinguere tre tipi di membri:

  • privato per i membri che sono accessibili solo alla classe stessa
  • pubblico per i membri accessibili al mondo
  • protetto per i membri accessibili ai discendenti

In C ++, c'è persino un idioma per usare funzioni virtuali private (e sovrascriverle in una classe derivata). Vedi questa domanda su SO per maggiori dettagli .

    
risposta data 25.08.2013 - 18:54
fonte

Leggi altre domande sui tag