Come dovrei nominare le funzioni che restituiscono valori in Python?


13

Sono confuso sulla scelta dei nomi per le mie funzioni in Python . A volte le funzioni integrate di Python sono indispensabili come: printfunzione e metodo stringa find. A volte non sono come: il lensuo nome non è un imperativo come calculate_len, ad esempio, e typenon lo è find_type.

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

Ma lenrestituisce un valore che usiamo e fa qualcosa (cioè calcolando quanti elementi ci sono in una sequenza o in una mappatura) e il suo nome non è indispensabile . D'altra parte, il findmetodo string (as len) restituisce un valore che usiamo e fa qualcosa, e il suo nome è indispensabile .

Ciò che ha fatto questa domanda è che ho messo uno script che crittografa e decrittografa la stringa usando il codice Caesar per essere rivisto. Il recensore ha affermato che:

Solo un istinto: le funzioni fanno cose. Quindi un buon nome per una funzione è un imperativo: userei rotate_letterinvece di rotated_letter.

rotated_letterrestituisce una stringa di una sola lettera che rappresenta una lettera ruotata di un numero. Non so cosa sia meglio, l'ho usato rotated_letterin quanto restituisce un valore, come la randintfunzione nel modulo casuale , non lo è generate_randint.

Quindi, in questo caso, come dovrei nominare una funzione che restituisce un valore da usare? Dovrei rendere il nome imperativo o solo un nome . In altri casi è ovvio come farlo, come funzioni booleane , come is_evene lo is_palindromefacciamo solo come una domanda sì / no , e anche funzioni che fanno e restituiscono valori non usati (ad es. None), Come il printmetodo e list sort.


questa è in realtà una pratica molto comune (direi una convenzione) per usare gli imperativi quando si nomina la funzione. Ad esempio, come si chiama una variabile che memorizza la lettera ruotata della funzione rotated_letter?
JoulinRouge,

Non è un buon modo di pensare ad alcuni dei tuoi esempi. len, ad esempio, è meglio pensarlo come "lunghezza di" - stai ottenendo una descrizione a livello di livello del suo argomento.
Izkata,

Risposte:


10

Usa i verbi dove ragionevole, i nomi se sono più brevi e inequivocabili

Il più delle volte, le funzioni dovrebbero essere verbi (imperativi) e le classi, le variabili e i parametri dovrebbero essere nomi. Gli attributi dovrebbero anche essere nomi, compresi quelli creati usando @property. Questo è particolarmente vero per le funzioni che hanno effetti collaterali. [1] Se una funzione restituisce qualcosa, dovresti valutare se il verbo aggiunge qualcosa o è solo "rumore":

  • make_list(foo)vs list(foo).: il sostantivo è più facile da leggere rispetto al verbo. Inoltre, in listrealtà è una classe e le classi dovrebbero essere nomi.
  • open(foo)vs file(foo).: Il verbo è più facile da leggere rispetto al sostantivo, e ha più senso dare "opzioni" a un verbo piuttosto che a un sostantivo, quindi il sostantivo è 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(assumiamo fooe barsono entrambi sostantivi): la prima opzione è subito chiara, perché "get" non aggiunge nulla che non sapevamo già. Il secondo è appropriato se baruscire da a fooè un'operazione potenzialmente costosa e / o comporta effetti collaterali (si potrebbe anche considerare Bar(foo)se Barè una classe). Il terzo è appropriato se si tratta di un'operazione economica senza effetti collaterali e è improbabile che implementazioni alternative lo rendano costoso .
  • xs.sort()vs. sorted(xs)if xsè un elenco: il primo è indispensabile: ordina l'elenco. Modifica l'elenco sul posto e non restituisce nulla. Il secondo è dichiarativo: un elenco ordinato, che è esattamente ciò che restituisce. Entrambi sono verbi.

[1]: in genere la restituzione di un valore e gli effetti collaterali si escludono a vicenda a meno che non si disponga di alcuni validi motivi di progettazione per combinarli. Quindi una funzione che ha effetti collaterali non dovrebbe probabilmente restituire nulla e quindi trasformarla in un nome avrebbe molto poco senso.
[2]: Ci sono alcune operazioni di livello moderatamente inferiore nel iomodulo che possono essere usate per aggiungere o rimuovere buffering di file, en / decodifica automatica del testo, ecc., E questi sono per lo più nomi 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 crea automaticamente.


Grazie! In " foo.get_bar() vs.` foo.bar ()` vs. foo.bar" qual è la differenza tra il secondo e il terzo ?
Mahmood Muhammad Nageeb,

Il terzo è una proprietà o un attributo nudo. Il secondo è un metodo.
Kevin,

Quindi, se capisco, è opportuno non rendere rotated_letterimperativo e mantenerlo dichiarativo, giusto?
Mahmood Muhammad Nageeb,

In questo caso non sono sicuro che lettersia implicito nel contesto.
Kevin,

+1 per menzionare listè una classe
Dušan Maďar,

0

rotated_letternon sembra un metodo. Sembra una proprietà. Ciò significa che la prima idea è di fare:

var letter = caesar.rotated_letter

aspettandosi letterdi contenere un valore di tipo stringa, non una funzione. Da lì, o hai scelto un nome diverso, come ad esempio:

def rotate_letter(self):
    pass

oppure usi invece una proprietà:

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

lene typesono chiamati così perché qualsiasi altro nome sarebbe lungo da digitare. Sono molto usati e hanno uno stato speciale delle funzioni principali di Python che ogni programmatore di Python imparerà comunque, rendendo i loro nomi molto più irrilevanti dei nomi delle librerie di terze parti.

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

Si noti che potrebbero esserci ragioni storiche anche per len: altri linguaggi, come C #, preferito Count, che di solito è un metodo (sebbene il comportamento sia purtroppo incoerente con .NET Framework). Countè un verbo, così intuitivamente, sei propenso a invocarlo come metodo.

Restituzione di valori o esecuzione di un'azione

Ci si aspetta 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 malapena return ...un'istruzione,

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

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

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

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

  • Può influire sull'ambiente e restituire un valore. Esempio: value.increment()usato come value++.

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

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


Presumo che la risposta sia "sì", ma devo chiedere: stai rispondendo interamente dal punto di vista di Python? Perché in altre lingue la tua separazione tra funzione e proprietà non è sempre vera; non è inoltre vero che una funzione "deve eseguire un'azione". È questa la convenzione in Python? (Scrivo Python ma non ho letto tutti i PEP e sicuramente NON sono un esperto. Non ho votato, BTW).
Andres F.

@AndresF .: Sto rispondendo dal punto di vista di Python. In linguaggi come Java dove non esistono proprietà getSomethinge setSomethingsono usati i soliti nomi al posto di proprietà.
Arseni Mourzenko,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.