Esiste una convenzione per la restituzione di più articoli?

7

In Python in particolare (non so se questo è generalizzato) c'è un modo "migliore" per restituire più oggetti da una funzione?

def func1():
    return a,b #equivalent to (a,b)

def func2():
    return[a,b]

def func3():
    return{"valueA":a,"valueB":b}

Il primo è quello che vedo più in generale, ma sento che l'ultimo crea un codice più leggibile perché hai un output con nome, ma potrei mancare una sorta di sovraccarico creato con questo metodo?

    
posta Devon Muraoka 06.08.2016 - 19:01
fonte

2 risposte

10

Penso che le scelte debbano essere considerate strettamente dal punto di vista del chiamante: qual è il consumatore più probabile che debba fare?

E quali sono le caratteristiche salienti di ciascuna collezione?

  • Si accede alla tupla in ordine e immutabile
  • Si accede alla lista in ordine e modificabile
  • È possibile accedere al comando tramite il tasto

L'elenco e la tupla sono equivalenti per l'accesso, ma l'elenco è mutabile. Beh, per me non è importante se il chiamante stacca immediatamente i risultati:

score, top_player = play_round(players)
# or
idx, record = find_longest(records)

Per me non c'è motivo di preoccuparsi se si tratta di una lista o di una tupla, e la tupla è più semplice su entrambi i lati.

D'altra parte, se la raccolta restituita verrà mantenuta intera e utilizzata come raccolta :

points = calculate_vertices(shape)
points.append(another_point)
# Make a new shape

allora potrebbe aver senso che il ritorno sia mutabile. Anche l'omogeneità è un fattore importante. Supponi di aver scritto una funzione per cercare una sequenza per motivi ripetuti. Le informazioni che ottengo sono l'indice nella sequenza della prima istanza del pattern, il numero di ripetizioni e il pattern stesso. Quelli non sono gli stessi tipi di cose. Anche se potrei tenere insieme i pezzi, non c'è motivo per cui io voglia cambiare la collezione . Questo non è un list .

Ora per il dizionario.

the last one creates more readable code because you have named outputs

Sì, avere le chiavi per i campi rende i dati eterogenei più espliciti, ma ha anche alcuni ingombri. Di nuovo, per il caso di "Sto solo andando a spacchettare le cose", questo

round_results = play_round(players)
score, top_player = round_results["score"], round_results["top_player"]

(anche se si evitano le stringhe letterali per le chiavi), è un'operazione non necessaria rispetto alla versione tupla.

La domanda qui è triplice: quanto è complessa la collezione, quanto sarà conservata la collezione insieme e avremo bisogno di usare questo stesso tipo di raccolta in un mucchio di luoghi diversi?

Suggerirei che un valore di ritorno ad accesso con chiave inizia ad avere più senso di una tupla quando ci sono più di tre membri circa, e specialmente dove c'è un nidificazione:

shape["transform"]["raw_matrix"][0, 1] 
# vs.
shape[2][4][0, 1]

Questo porta alla domanda successiva: la raccolta lascerà intatto questo ambito, lontano dalla chiamata che lo ha creato? L'accesso con chiave laggiù aiuterà assolutamente la comprensibilità.

La terza domanda: riutilizzare indica un semplice tipo di dati personalizzato come una quarta opzione che non hai presentato.

La struttura è di proprietà di questa sola funzione? O stai creando lo stesso layout di dizionario in molti posti? Molte altre parti del programma devono funzionare su questa struttura? Un layout di dizionario ripetuto dovrebbe essere scomposto in una classe. Il bonus è che puoi collegare il comportamento: forse alcune delle funzioni che operano sui dati vengono incapsulate come metodi.

Una quinta opzione buona, leggera, è namedtuple() . Questa è in sostanza la forma immutabile del valore di ritorno del dizionario.

    
risposta data 06.08.2016 - 23:31
fonte
1

Non pensare alle funzioni che restituiscono più argomenti. Concettualmente, è meglio pensare a funzioni come ricevere e restituire un singolo argomento. Una funzione che sembra accettare più argomenti riceve in realtà solo un argomento singolo di tupla (formalmente prodotto ) genere. Allo stesso modo, una funzione che restituisce più argomenti sta semplicemente restituendo una tupla.

In Python:

def func(a, b, c):
  return b, c

potrebbe essere riscritto come

def func(my_triple):
  return (my_triple[1], my_triple[2])

per rendere il confronto ovvio.

Il primo caso è semplicemente zucchero sintattico per quest'ultimo; entrambi ricevono una tripla come argomento, ma il primo schema coincide con il suo argomento per eseguire la destrutturazione automatica nelle sue componenti costitutive. Pertanto, anche le lingue senza general pattern matching ammettono alcune forme di matching di pattern di base su alcuni dei loro tipi (Python ammette la corrispondenza del modello su entrambi i tipi di prodotto e di registrazione).

Per tornare alla domanda in questione: non c'è una sola risposta alla tua domanda, perché sarebbe come chiedere "quale dovrebbe essere il tipo di ritorno di una funzione arbitraria"? Dipende dalla funzione e dal caso d'uso. E, incidentalmente, se i "valori di ritorno multipli" sono davvero indipendenti, allora dovrebbero probabilmente essere calcolati da funzioni separate.

    
risposta data 06.08.2016 - 21:33
fonte

Leggi altre domande sui tag