Come dovrei nominare le funzioni che restituiscono valori in Python?

8

Sono confuso riguardo alla scelta dei nomi per le mie funzioni in Python . A volte le funzioni integrate Python sono imperative come: print function e string method find . A volte non sono tali: len il suo nome non è imperativo come calculate_len , per esempio, e type non è find_type .

Posso capire che print restituisce un valore che non usiamo (cioè None ) e fa qualcosa (cioè mostra una stringa sullo schermo), quindi il suo nome è imperativo.

Ma len restituisce un valore che usiamo e fa qualcosa (cioè calcolando quanti elementi ci sono in una sequenza o una mappatura) e il suo nome non è imperativo . D'altra parte, il metodo di stringa find (come len ) restituisce un valore che usiamo e fa qualcosa, e il suo nome è imperativo .

Ciò che ha reso questa domanda è che ho inserito uno script che crittografa e decodifica la stringa usando il codice Caesar per essere revisionato. Il revisore ha detto che:

Just a gut feeling: functions do stuff. So a good name for a function is an imperative: I'd use rotate_letter instead of rotated_letter.

rotated_letter restituisce una stringa a lettera singola che rappresenta una lettera ruotata di un numero. Non so cosa sia meglio, ho usato rotated_letter perché restituisce un valore, come randint funzione in modulo casuale , non è generate_randint .

Quindi, in questo caso, come dovrei nominare una funzione che restituisce un valore da utilizzare? Devo pronunciare il nome imperativo o solo un nome . In altri casi è ovvio come farlo, ad esempio funzioni booleane , come is_even e is_palindrome lo rendiamo semplicemente come una sì / nessuna domanda , e funziona anche solo per fare e restituire valori non utilizzati (cioè None ), come print e list metodo sort .

    
posta Mahmud Muhammad Naguib 20.10.2016 - 13:24
fonte

2 risposte

7

Usa i verbi dove sono ragionevoli, i nomi se sono più brevi e non ambigui

La maggior parte delle volte le funzioni dovrebbero essere verbo (imperativo) e le classi, le variabili e i parametri dovrebbero essere nomi. Gli attributi dovrebbero essere anche nomi, compresi quelli creati usando @property . Questo è particolarmente vero per le funzioni che hanno effetti collaterali. [1] Se una funzione restituisce qualcosa, devi valutare se il verbo aggiunge qualcosa o è solo "disturbo":

  • make_list(foo) vs. list(foo) : il nome è più facile da leggere rispetto al verbo. Inoltre, list è in realtà una classe e le classi dovrebbero essere sostantivi.
  • open(foo) vs. file(foo) : il verbo è più facile da leggere rispetto al sostantivo, e ha più senso dare "opzioni" a un verbo che a un nome, quindi il nome è stato rimosso in Python 3. open() rimane l'unico modo "standard" [2] per creare oggetti file in Python 3.
  • foo.get_bar() vs. foo.bar() vs. foo.bar (supponiamo foo e bar sono entrambi nomi): la prima opzione è giusta, perché il "get" non aggiunge nulla che non abbiamo già conoscere. Il secondo è appropriato se ottenere un bar su un foo è un'operazione potenzialmente costosa e / o comporta effetti collaterali (potresti anche considerare Bar(foo) se Bar è una classe). Il terzo è appropriato se si tratta di un'operazione a basso costo senza effetti collaterali, e le implementazioni alternative non dovrebbero renderlo costoso .
  • xs.sort() vs. sorted(xs) se xs è un elenco: il primo è imperativo: ordina l'elenco. Modifica l'elenco sul posto e non restituisce nulla. Il secondo è dichiarativo: una lista che è ordinata, che è precisamente ciò che restituisce. Entrambi sono verbi.

[1]: in genere restituisce un valore e gli effetti collaterali si escludono a vicenda, a meno che non vi sia un motivo di progettazione convincente per combinarli. Quindi una funzione che ha effetti collaterali probabilmente non dovrebbe restituire nulla e quindi renderlo un sostantivo non avrebbe molto senso.
[2]: Ci sono alcune operazioni di livello moderatamente inferiore nel modulo io che possono essere utilizzate per aggiungere o rimuovere il buffering dei file, l'en / decoding automatico del testo, ecc. E sono principalmente sostantivi perché sono classi orientate agli oggetti . La maggior parte degli utenti non ha bisogno di giocare direttamente con queste cose; invece, open() sceglie una classe appropriata e la istanzia automaticamente.

    
risposta data 20.10.2016 - 23:27
fonte
-1

rotated_letter non sembra un metodo. Sembra una proprietà. Ciò significa che la prima idea è:

var letter = caesar.rotated_letter

aspettando letter per contenere un valore di tipo stringa, non una funzione. Da lì, o hai scelto un nome diverso, ad esempio:

def rotate_letter(self):
    pass

oppure usi una proprietà invece:

@property
def rotated_letter(self):
    return self.whatever

len e type sono nominati così perché qualsiasi altro nome sarebbe lungo da digitare. Sono molto usati e hanno uno status speciale delle funzioni core di Python che ogni programmatore Python imparerà comunque, rendendo i loro nomi molto più irrilevanti dei nomi delle librerie di terze parti.

len , in particolare, è un buon esempio di ciò che non dovresti fare nel tuo codice: ti conviene usare nomi completi come length (a meno che la forma abbreviata sia molto popolare, come max ), e usa un verbo, come compute_length . Oppure potrebbe essere una proprietà: len([1, 5, 6]) diventa [1, 5, 6].length . Ad esempio, in C #, viene utilizzato il modulo successivo: new [] { ... }.Length .

Si noti che potrebbero esserci motivi storici anche per len : altri linguaggi, come C #, preferito Count , che è di solito un metodo (sebbene il comportamento sfortunatamente sia incoerente. NET Framework). Count è un verbo, quindi intuitivamente, sei incline a invocarlo come metodo.

Restituzione di valori o esecuzione di un'azione

Si presume sempre che una funzione esegua un'azione. Se restituisce a malapena un valore, dovrebbe essere una proprietà. Hai un suggerimento che la funzione dovrebbe essere trasformata in una proprietà quando:

  • La funzione contiene a mala pena un'istruzione return ... ,

  • Il nome della funzione che ti viene in mente naturalmente è get_something , come in product.get_price() .

Ora, se hai una funzione, può essere uno dei quattro tipi:

  • Può essere puro, ovvero restituire un valore senza influire sull'ambiente. Esempio: road.measure_distance() .

  • Può influenzare l'ambiente senza restituire nulla. Esempio: product_database.remove_record(1234) .

  • Può influenzare l'ambiente e restituire un valore. Esempio: value.increment() utilizzato come value++ .

  • Non può fare nulla e non restituire nulla. Esempio: time.sleep(1) .

Ci sono pochi casi in cui il nome potrebbe dare un strong suggerimento sul tipo di funzione, ma in molti casi, non sarai in grado di conoscere il tipo a malapena dal suo nome.

    
risposta data 20.10.2016 - 15:23
fonte

Leggi altre domande sui tag