Scopo di 'return self' da un metodo di classe?

43

Mi sono imbattuto in qualcosa di simile in un progetto open source. I metodi che modificano gli attributi di istanza restituiscono un riferimento all'istanza. Qual è lo scopo di questo costrutto?

class Foo(object):

  def __init__(self):
    self.myattr = 0

  def bar(self):
    self.myattr += 1
    return self
    
posta nate c 23.12.2010 - 22:55
fonte

5 risposte

64

Serve per concatenare.

Ad esempio:

var Car = function () {
    return {
        gas : 0,
        miles : 0,
        drive : function (d) {
            this.miles += d;
            this.gas -= d;
            return this;
        },
        fill : function (g) {
            this.gas += g;
            return this;
        },
    };
}

Ora puoi dire:

var c = Car();
c.fill(100).drive(50);
c.miles => 50;
c.gas => 50;
    
risposta data 23.12.2010 - 23:07
fonte
10

Come @Lie Ryan e @Frank Shearar menzionano, si parla di "interfaccia fluente", ma quel modello è in circolazione da molto tempo.

La parte controversa di questo modello è che in OO si ha uno stato mutabile, quindi un metodo void ha un tipo di valore di ritorno implicito di this - cioè, l'oggetto con stato aggiornato è una specie di valore di ritorno .

Quindi in un linguaggio OO con stato mutabile, questi due sono più o meno equivalenti:

a.doA()
a.doB()
a.doC()

... al contrario di

a.doA().doB().doC()

Quindi ho sentito persone in passato resistere a interfacce fluide perché amano la prima forma. Un altro nome che ho sentito per "fluent interface" è "train wreck";)

Dico "più o meno equivalente", però, perché le interfacce fluenti aggiungono una ruga. Non devono "restituire questo". Possono "tornare indietro". È un modo per raggiungere oggetti immutabili in OO.

Quindi potresti avere una classe A che fa (pseudocodice)

function doA():
    return new A(value + 1)

function doB():
    return new A(value * 2)

function doC():
    return new A(sqrt(value))

Ora, ogni metodo restituisce un oggetto nuovo di zecca, lasciando invariato l'oggetto iniziale. E questo è un modo per entrare in oggetti immutabili senza realmente cambiare molto nel tuo codice.

    
risposta data 22.04.2014 - 17:26
fonte
8

La maggior parte delle lingue sono consapevoli dell'idioma del "ritorno in sé", e lo ignorano se lo è non usato in una linea. Tuttavia è degno di nota il fatto che in Python, funzioni restituisce None per impostazione predefinita.

Quando ero a scuola CS, il mio istruttore ha fatto un accordo enorme su la differenza tra funzioni, procedure, routine e metodi; molte domande sui saggi a mano-cramping sono state messe a fuoco con matite meccaniche che si sono scaldate tra le mie mani su tutto ciò.

Basti dire che il ritorno di sé è il modo OO definitivo di creare metodi di classe, ma Python consente più valori di ritorno, tuple, liste, oggetti, primitive o Nessuna.

Chaining, come dicono, sta semplicemente mettendo la risposta all'ultima operazione nel prossimo, e il runtime di Python può ottimizzare quel genere di cose. La comprensione delle liste è una forma incorporata di questo. (Molto potente!)

Quindi in Python non è così importante che ogni metodo o funzione restituisca qualcosa, ecco perché il valore predefinito è Nessuno.

C'è una scuola di pensiero che ogni azione in un programma dovrebbe riportare il suo successo, fallimento o risultato al suo contesto o oggetto invocante, ma poi non stavano parlando i requisiti ADA di DOD qui. Se hai bisogno di ricevere un feedback un metodo, vai avanti o no, ma cerca di essere coerente a riguardo.

Se un metodo può fallire, dovrebbe restituire successo o fallimento o generare un'eccezione da gestire.

Un avvertimento è che se si utilizza il ritorno self idiom, Python ti permetterà di assegnare tutti i tuoi metodi alle variabili e potresti pensare che stai ricevendo un risultato di dati o un elenco quando stai effettivamente ricevendo l'oggetto.

I linguaggi restrittivi di tipo urlano e urlano e si spezzano quando provi a farlo, ma quelli interpretati (Python, Lua, Lisp) sono molto più dinamici.

    
risposta data 10.10.2012 - 05:48
fonte
4

In Smalltalk, ogni metodo che non restituisce esplicitamente qualcosa, ha un implicito "return self".

Questo perché (a) avere qualsiasi metodo restituisce qualcosa rende il modello di calcolo più uniforme e (b) è molto utile avere metodi di ritorno self. Josh K dà un bell'esempio.

    
risposta data 24.12.2010 - 00:09
fonte
1

Vantaggi della restituzione di un oggetto ( return self )

  • Esempio:

    print(foo.modify1().modify2())
    
    # instaed of
    foo.modify1()
    foo.modify2()
    print(foo)
    
  • Stile più popolare nella comunità di programmazione (credo).

Vantaggi della mutazione di un oggetto (no return self )

  • Possibilità di utilizzare return per altri scopi.
  • Guido van Rossum approva questo stile (I non sono d'accordo con la sua argomentazione).
  • Stile più popolare nella comunità Python (credo)
  • Predefinito (meno codice sorgente).
risposta data 09.12.2016 - 16:29
fonte

Leggi altre domande sui tag