Domanda

In Python, puoi fare in modo che una funzione restituisca più valori.Ecco un esempio inventato:

def divide(x, y):
    quotient = x/y
    remainder = x % y
    return quotient, remainder  

(q, r) = divide(22, 7)

Sembra molto utile, ma sembra che se ne possa anche abusare ("Bene... la funzione X calcola già ciò di cui abbiamo bisogno come valore intermedio.Facciamo in modo che X restituisca anche quel valore").

Quando dovresti tracciare la linea e definire un metodo diverso?

È stato utile?

Soluzione

Assolutamente (per l'esempio che hai fornito).

Le tuple sono cittadini di prima classe in Python

C'è una funzione incorporata divmod() fa esattamente questo.

q, r = divmod(x, y) # ((x - x%y)/y, x%y) Invariant: div*y + mod == x

Ci sono altri esempi: zip, enumerate, dict.items.

for i, e in enumerate([1, 3, 3]):
    print "index=%d, element=%s" % (i, e)

# reverse keys and values in a dictionary
d = dict((v, k) for k, v in adict.items()) # or 
d = dict(zip(adict.values(), adict.keys()))

A proposito, le parentesi non sono necessarie la maggior parte delle volte.Citazione da Riferimento alla libreria Python:

Le tuple possono essere costruite in diversi modi:

  • Utilizzando una coppia di parentesi per denotare la tupla vuota:()
  • Utilizzando una virgola finale per una tupla singleton:a, o (a,)
  • Separare gli elementi con virgole:a, b, c o (a, b, c)
  • Usando la tuple() integrata:tuple() o tuple(iterabile)

Le funzioni dovrebbero avere un unico scopo

Pertanto dovrebbero restituire un singolo oggetto.Nel tuo caso questo oggetto è una tupla.Considera la tupla come una struttura dati composta ad hoc.Esistono linguaggi in cui quasi ogni singola funzione restituisce più valori (elenco in Lisp).

A volte è sufficiente ritornare (x, y) invece di Point(x, y).

Tuple con nome

Con l'introduzione delle tuple con nome in Python 2.6 è preferibile in molti casi restituire tuple con nome invece di tuple semplici.

>>> import collections
>>> Point = collections.namedtuple('Point', 'x y')
>>> x, y = Point(0, 1)
>>> p = Point(x, y)
>>> x, y, p
(0, 1, Point(x=0, y=1))
>>> p.x, p.y, p[0], p[1]
(0, 1, 0, 1)
>>> for i in p:
...   print(i)
...
0
1

Altri suggerimenti

Innanzitutto, nota che Python consente quanto segue (non sono necessarie le parentesi):

q, r = divide(22, 7)

Per quanto riguarda la tua domanda, in ogni caso non esiste una regola ferrea.Per esempi semplici (e solitamente inventati), può sembrare che sia sempre possibile che una determinata funzione abbia un unico scopo, risultando in un unico valore.Tuttavia, quando si utilizza Python per applicazioni del mondo reale, ci si imbatte rapidamente in molti casi in cui è necessaria la restituzione di più valori e il risultato è un codice più pulito.

Quindi, direi di fare tutto ciò che ha senso e di non cercare di conformarsi a una convenzione artificiale.Python supporta più valori restituiti, quindi usalo quando appropriato.

L'esempio che fornisci è in realtà una funzione incorporata di Python, chiamata divmod.Quindi qualcuno, ad un certo punto, ha pensato che fosse abbastanza Pythonico da includerlo nelle funzionalità principali.

Per me, se rende il codice più pulito, è Pythonic.Confronta questi due blocchi di codice:

seconds = 1234
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)

seconds = 1234
minutes = seconds / 60
seconds = seconds % 60
hours = minutes / 60
minutes = minutes % 60

Sì, restituire più valori (ad esempio una tupla) è decisamente pitonico.Come altri hanno sottolineato, ci sono molti esempi nella libreria standard Python, così come in progetti Python di tutto rispetto.Due commenti aggiuntivi:

  1. Restituire più valori a volte è molto, molto utile.Prendiamo, ad esempio, un metodo che facoltativamente gestisce un evento (restituendo un valore nel farlo) e restituisce anche un successo o un fallimento.Ciò potrebbe verificarsi in un modello di catena di responsabilità.In altri casi, si desidera restituire più dati strettamente collegati, come nell'esempio fornito.In questa impostazione, restituire più valori è simile a restituire una singola istanza di una classe anonima con diverse variabili membro.
  2. La gestione degli argomenti del metodo da parte di Python richiede la capacità di restituire direttamente più valori.In C++, ad esempio, gli argomenti del metodo possono essere passati per riferimento, quindi è possibile assegnare loro valori di output, oltre al valore restituito formale.In Python, gli argomenti vengono passati "per riferimento" (ma nel senso di Java, non di C++).Non è possibile assegnare nuovi valori agli argomenti del metodo e rifletterli all'esterno dell'ambito del metodo.Per esempio:

    // C++
    void test(int& arg)
    {
        arg = 1;
    }
    
    int foo = 0;
    test(foo); // foo is now 1!
    

    Confrontare con:

    # Python
    def test(arg):
        arg = 1
    
    foo = 0
    test(foo) # foo is still 0
    

E' decisamente pitone.Il fatto che puoi restituire più valori da una funzione è il boilerplate che avresti in un linguaggio come C in cui devi definire una struttura per ogni combinazione di tipi che restituisci da qualche parte.

Tuttavia, se raggiungi il punto in cui restituisci qualcosa di pazzesco come 10 valori da una singola funzione, dovresti seriamente considerare di raggrupparli in una classe perché a quel punto diventa ingombrante.

Restituire una tupla è interessante.Nota anche il nuovo denominata THETUPLE che è stato aggiunto in Python 2.6 che può renderlo più appetibile per te:http://docs.python.org/dev/library/collections.html#collections.namedtuple

OT:Algol68 di RSRE ha il curioso operatore "/:=".per esempio.

INT quotient:=355, remainder;
remainder := (quotient /:= 113);

Dando un quoziente di 3 e un resto di 16.

Nota:in genere il valore di "(x/:=y)" viene scartato poiché il quoziente "x" viene assegnato per riferimento, ma nel caso di RSRE il valore restituito è il resto.

cfr. Aritmetica dei numeri interi - Algol68

È possibile restituire più valori utilizzando una tupla per funzioni semplici come divmod.Se rende leggibile il codice, è Pythonic.

Se il valore restituito inizia a creare confusione, controlla se la funzione sta facendo troppo e, se lo è, suddividila.Se una tupla grande viene utilizzata come oggetto, rendila un oggetto.Inoltre, considera l'utilizzo tuple nominate, che farà parte della libreria standard in Python 2.6.

Sono abbastanza nuovo in Python, ma la tecnica della tupla mi sembra molto pitonica.Tuttavia, ho avuto un'altra idea che potrebbe migliorare la leggibilità.L'utilizzo di un dizionario consente l'accesso ai diversi valori per nome anziché per posizione.Per esempio:

def divide(x, y):
    return {'quotient': x/y, 'remainder':x%y }

answer = divide(22, 7)
print answer['quotient']
print answer['remainder']
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top