Como devo nomear funções que retornam valores em Python?

13

Estou confuso sobre a escolha de nomes para minhas funções em Python . Às vezes, as funções internas do Python são imperativas , como: printfunction e método de string find. Às vezes, eles não são assim: lenseu nome não é imperativo como calculate_len, por exemplo, e typenão é find_type.

Eu posso entender que printretorna um valor que não usamos (ou seja None) e faz alguma coisa (ou seja, mostra uma string na tela), por isso seu nome é imperativo.

Mas lenretorna um valor que usamos e faz alguma coisa (ou seja, calcular quantos itens existem em uma sequência ou um mapeamento.) E seu nome não é obrigatório . Por outro lado, o findmétodo string (as len) retorna um valor que usamos e fazemos algo, e seu nome é imperativo .

O que fez essa pergunta é que eu coloquei um script que criptografa e descriptografa a string usando a cifra de César para ser revisado. O revisor disse que:

Apenas um pressentimento: funções fazem coisas. Portanto, um bom nome para uma função é um imperativo: eu usaria em rotate_lettervez de rotated_letter.

rotated_letterretorna uma sequência de uma letra representando uma letra girada por um número. Eu não sei o que é melhor, usei rotated_lettercomo ele retorna um valor, como randintfunção no módulo aleatório , não é generate_randint.

Portanto, neste caso, como devo nomear uma função que retorna um valor a ser usado? Devo tornar o nome imperativo ou apenas um substantivo . Em outros casos, é óbvio como fazê-lo, como funções booleanas , como is_evene is_palindromeapenas fazemos uma pergunta sim / não , e também funções que apenas fazem e retornam valores não utilizados (ou seja None), como printmétodo list sort.

Mahmood Muhammad Nageeb
fonte
na verdade, é uma prática muito comum (eu diria uma convenção) usar imperativos ao nomear funções. Por exemplo, como você nomeia uma variável que armazena a letra girada da função rotated_letter?
JoulinRouge
Essa não é uma boa maneira de pensar em alguns de seus exemplos. len, por exemplo, é melhor pensado como "comprimento de" - você está obtendo uma descrição em nível meta do argumento.
Izkata

Respostas:

10

Use verbos, quando razoáveis, substantivos, se forem mais curtos e inequívocos

Na maioria das vezes, as funções devem ser verbos (imperativos) e as classes, variáveis ​​e parâmetros devem ser substantivos. Os atributos também devem ser substantivos, incluindo aqueles criados usando @property. Esse é especialmente o caso de funções com efeitos colaterais. [1] Se uma função retornar algo, você deve avaliar se o verbo adiciona algo ou é apenas "ruído":

  • make_list(foo)vs list(foo).: O substantivo é mais fácil de ler que o verbo. Além disso, listé realmente uma classe, e as classes devem ser substantivos.
  • open(foo)vs file(foo).: o verbo é mais fácil de ler do que o substantivo, e faz mais sentido dar "opções" a um verbo do que a um substantivo; portanto, o substantivo foi removido no Python 3. open()permanece o único caminho "padrão" [2] para criar objetos de arquivo no Python 3.
  • foo.get_bar()vs. foo.bar()vs. foo.bar(assuma fooe barsão ambos substantivos): A primeira opção está correta, porque o "get" não adiciona nada que ainda não conhecíamos. O segundo é apropriado se tirar uma barfolga fooé uma operação potencialmente cara e / ou traz efeitos colaterais (você também pode considerar Bar(foo)se Barfor uma classe). O terceiro é apropriado se for uma operação barata, sem efeitos colaterais, e é improvável que implementações alternativas a tornem cara .
  • xs.sort()vs. sorted(xs)if xsé uma lista: o primeiro é imperativo: classifique a lista. Ele modifica a lista no local e não retorna nada. O segundo é declarativo: uma lista que é ordenada, e é exatamente isso que ela retorna. Ambos são verbos.

[1]: Normalmente, retornar um valor e ter efeitos colaterais são mutuamente exclusivos, a menos que você tenha algum motivo atraente de design para combiná-los. Portanto, uma função que tenha efeitos colaterais provavelmente não deve retornar nada e, portanto, torná-la um substantivo faria muito pouco sentido.
[2]: Existem algumas operações de nível moderadamente mais baixo no iomódulo que podem ser usadas para adicionar ou remover buffer de arquivo, en / decodificação automática de texto, etc., e estes são principalmente substantivos porque são classes orientadas a objetos. A maioria dos usuários não precisa jogar diretamente com essas coisas; em vez disso, open()escolhe uma classe apropriada e a instancia automaticamente.

Kevin
fonte
Obrigado! Em " foo.get_bar() vs.` foo.bar ()` vs. foo.bar" qual é a diferença entre o segundo e o terceiro ?
Mahmood Muhammad Nageeb 21/10
O terceiro é uma propriedade ou um atributo simples. O segundo é um método.
21416 Kevin
Então, se eu entendi, é apropriado não tornar rotated_letterimperativo e mantê-lo declarativo, certo?
Mahmood Muhammad Nageeb 21/10
Nesse caso, não tenho certeza se letterestá implícito no contexto.
21416 Kevin
+1 para mencionar listé uma classe
Dušan Maďar 18/07/19
0

rotated_letternão parece um método. Parece uma propriedade. O que significa que a primeira ideia é fazer:

var letter = caesar.rotated_letter

esperando letterconter um valor do tipo string, não uma função. A partir daí, você escolheu um nome diferente, como:

def rotate_letter(self):
    pass

ou você usa uma propriedade:

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

lene typesão nomeados assim porque qualquer outro nome seria longo para digitar. Eles são muito usados ​​e têm um status especial das principais funções do Python que todo programador de Python aprenderá de qualquer maneira, tornando seus nomes muito mais irrelevantes do que os nomes de bibliotecas de terceiros.

len, especialmente, é um bom exemplo do que você não deve fazer no seu código: espera-se que você use nomes completos como length(a menos que o formato abreviado seja muito popular, como max) e use um verbo, como compute_length. Ou poderia ser uma propriedade: len([1, 5, 6])torna - se [1, 5, 6].length. Por exemplo, em C #, a forma mais tarde é utilizada: new [] { ... }.Length.

Observe que também pode haver motivos históricos para len: outros idiomas, como C #, preferidos Count, que geralmente são um método (embora o comportamento seja infelizmente inconsistente no .NET Framework). Counté um verbo, de maneira intuitiva, você costuma invocá-lo como método.

Retornando valores ou executando uma ação

Espera-se sempre que uma função execute uma ação. Se ele mal retornar um valor, deve ser uma propriedade. Você tem uma dica de que a função deve ser transformada em uma propriedade quando:

  • A função mal contém uma return ...declaração,

  • O nome da função que vem naturalmente à sua mente é get_something, como em product.get_price().

Agora, se você tiver uma função, ela poderá ser um dos quatro tipos:

  • Pode ser puro, ou seja, retornar um valor sem afetar o meio ambiente. Exemplo: road.measure_distance().

  • Pode afetar o ambiente sem retornar nada. Exemplo: product_database.remove_record(1234).

  • Isso pode afetar o ambiente e retornar um valor. Exemplo: value.increment()usado como value++.

  • Não pode fazer nada e retornar nada. Exemplo: time.sleep(1).

Existem poucos casos em que o nome pode dar uma dica forte sobre o tipo da função, mas em muitos casos, você não poderá conhecer o tipo apenas pelo nome.

Arseni Mourzenko
fonte
Suponho que a resposta seja "sim", mas devo perguntar: você está respondendo inteiramente da perspectiva do Python? Porque em outros idiomas sua separação de função versus propriedade nem sempre é verdadeira; Também não é verdade que uma função "deve executar uma ação". Esta é a convenção em Python? (Eu escrevo Python, mas não li todos os PEPs e definitivamente não sou um especialista. Não diminuí a votação, BTW).
Andres F.
@AndresF .: Estou respondendo da perspectiva do Python. Em linguagens como Java, onde as propriedades não existem getSomethinge setSomethingsão os nomes comuns usados ​​em vez de propriedades.
Arseni Mourzenko