Python ha alcune caratteristiche che possono essere utilizzate per incapsulare dati privati?

0

Solitamente nel mondo OOP ci viene detto che la modularità è una buona pratica e che mantenere un accoppiamento libero tra i moduli è una grande cosa. L'incapsulamento ci aiuta a raggiungere questo accoppiamento lento.

L'incapsulamento Java è ottenuto tramite modificatori di accesso , in Ruby abbiamo regole più rigide tramite attr_accessor .

Ma per quanto riguarda Python? Vedo che non posso nascondere i miei campi o metodi se non usando trucchi come __ davanti ai nomi. È questo il solo / corretto modo per ottenere l'incapsulamento in Python?

    
posta CodeYogi 19.11.2015 - 17:41
fonte

2 risposte

6

Dai un'occhiata al seguente codice C ++:

#include<iostream>
using namespace std;

class Foo {
    private:
        int x;

    public:
        Foo(int x): x(x) {}

        void printX() {
            cout << "My x is " << x << endl;
        }
};

int main(int argc, char** argv) {
    Foo foo(12);
    foo.printX(); // prints "My x is 12"

    //foo.x = 13; // error: ‘int Foo::x’ is private

    *((int*) &foo) = 14;
    foo.printX(); // prints "My x is 14"

    return 0;
}

Ho infranto l'incapsulamento lanciando un puntatore. Significa che l'incapsulamento è rotto in C ++? No - perché nessuno sano di mente lo farebbe! Trasmetti a tuo rischio e pericolo.

È lo stesso con Python - usa i campi con prefisso _ a tuo rischio. L'incapsulamento è per sicurezza - non per sicurezza. Non si inseriscono chiavi private in campi privati e si ha fiducia nell'incapsulazione per impedire agli utenti di toccarli. Usi l'incapsulamento per proteggere gli utenti delle tue classi dai dettagli di implementazione interni e se questi utenti non rispettano la convenzione di Python è il loro dannato problema.

    
risposta data 19.11.2015 - 18:29
fonte
0

Puoi usare @property annotazioni per implementare getter e setter à la Java o Ruby. Questi forniscono una qualche forma di incapsulamento pur consentendo agli utenti della tua classe di accedere agli attributi in modo Python.

Supponiamo che tu abbia una classe con un attributo name rivolto al pubblico, ma i nomi devono essere sotto una certa lunghezza.

class Foo(object):

    def __init__(self, name: str):
        if len(name) <= 3:
            self.name = name
        else:
            raise TypeError

In questo caso, la lunghezza del valore name viene verificata all'istanziazione ma non da allora in poi; potresti usare un _name attributo e un brutto get_name() e set_name() metodi, ma usando @property annotazioni come sotto, puoi fare un controllo di validità per l'attributo ogni volta che viene impostato mentre ancora lo si consente di accedervi nel Python convenzionale modo, cioè per mezzo di espressioni come foo.name e foo.name = 'xyz' .

class Foo(object):

    def __init__(self, name: str):
        self.name = name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, new_name: str):
        if len(new_name) <= 3:
            self._name = new_name
        else:
            raise TypeError

Come menzionato da Idan, _ -prefixing di metodi / attributi privati è solo una convenzione (seguita con molta attenzione) e un utente potrebbe ancora manipolare il valore dell'attributo se lo desiderava davvero, ad es. di foo._name = 'abcdef' .

    
risposta data 20.11.2015 - 06:26
fonte

Leggi altre domande sui tag