Assegnazione di variabili di istanza in una funzione chiamata da __init__ vs. funzione chiamata da __init__

-1

Se ho bisogno di avere una funzione, esegui qualche elaborazione per inizializzare più variabili dell'oggetto (sto avendo difficoltà a trovare un semplice esempio che non sembri strano).

Quale dei seguenti modelli è preferibile?

class foo( object ):
    def __init__(self, bar, bar2):
        self.bar = bar
        self.baz, self.square_baz = self.func(bar2)

    def func(self, bar2):
        return self.bar + bar2, bar2 * ba2

o

class foo( object ):
    def __init__(self, bar, bar2):
        self.bar = bar
        self.func(bar2)

    def func(self, bar2):
        self.baz = self.bar + bar2
        self.square_baz = bar2 * bar2

Mi sento come nel primo modello, il costruttore __init__ e l'elaborazione func sono ben disaccoppiati. Ed è facile dire quali variabili conterranno ciascuna istanza di foo . D'altra parte, dover restituire più variabili da una funzione per assegnarle a un oggetto sembra ... brutto, tuttavia questa sembra essere una conseguenza della libreria che sto usando.

    
posta raphael 17.01.2017 - 22:19
fonte

2 risposte

2

Non esiste un luogo ufficiale per registrare tutte le variabili di istanza in Python, né può esserci, dal momento che si possono aggiungere dinamicamente nuove variabili di istanza, in qualsiasi momento della vita dell'oggetto.

Tuttavia, è bello avere un singolo posto dove guardare (e gli IDE da guardare, come dice @RemcoGerlich) per identificare quali variabili di istanza sono in genere in gioco. La mia soluzione è di inizializzare tutte le variabili di istanza comuni in __init__ , anche se solo a un valore fittizio di None che verrà rapidamente sovrascritto. Questo evita l'assegnazione di più valori più brutti, ma offre a umani e IDE un posto unico per cercare una panoramica dei valori.

class foo(object):
    def __init__(self, bar, bar2):
        self.bar = bar
        self.baz = None
        self.square_baz = None
        self.func(bar2)

    def func(self, bar2):
        self.baz = self.bar + bar2
        self.square_baz = bar2 * bar2

Questo esempio utilizza un nome di metodo standard "pubblico" func come inizializzatore. Se func verrebbe normalmente chiamato al di fuori della classe, questo ha senso. Spesso, tuttavia, la funzione chiamata da __init__ sarà privata (solitamente chiamata solo dalla classe e solo una volta o raramente). In tal caso, puoi dare ulteriore chiarezza dandogli un nome più indicativo e utilizzando un prefisso di sottolineatura per il nome del metodo, che convenzionalmente significa "questo è un metodo privato". Quindi potrei chiamarlo _initialize o _finish_initialization per esempio. (Tecnicamente parlando, Python non ha "metodi privati", almeno non nei linguaggi di tipo scope forzato come Java. I metodi privati sono gestiti per convenzione / idioma, anche se non forzati.)

    
risposta data 18.01.2017 - 21:55
fonte
1

Onestamente, non farei nessuno dei due. func non sembra affatto che dovrebbe essere un metodo di istanza - considera, se qualcuno ha un foo object f , perché mai vorrebbe chiamare f.func() ?

Se è probabile che bar e bar2 cambino durante la vita di un oggetto (cioè dopo __init__ ), allora la cosa migliore è probabilmente solo per:

class foo( object ):
    def __init__(self, bar, bar2):
        self.bar = bar
        self.bar2 = bar2

    @property
    def baz(self):
        return self.bar + self.bar2

    @property
    def square_baz(self):
        return self.bar2 * self.bar2

Quindi potresti cambiare liberamente f.bar e f.bar2 e sarai sempre sicuro che f.baz e f.square_baz rimarranno sincronizzati con loro.

Ma, ad essere onesti, probabilmente non farei nemmeno quello. Probabilmente farei semplicemente la cosa ovvia (calcola e assegna tutto in __init__ ).

class foo( object ):
    def __init__(self, bar, bar2):
        self.bar = bar
        self.baz = bar + bar2
        self.square_baz = bar2 * bar2

Senza sapere perché non puoi o non vuoi farlo, non sono sicuro di cosa consigliare.

    
risposta data 30.01.2017 - 19:21
fonte

Leggi altre domande sui tag