Existe algum estilo de codificação recomendado / geralmente aceito para lidar com situações em que uma função retorna uma tupla de valores, mas apenas um desses valores é usado posteriormente (observe que isso se destina principalmente a funções de biblioteca que não posso alterar - escrevendo um wrapper a ligação provavelmente é um pouco exagerada ...)? Em vez de fazer
a, b, c = foo()
e, em seguida, apenas não usando b
e c
, qual das seguintes variantes deve ser preferida (ou existe outra?):
Variante 1 (sublinhado)
a, _, _ = foo()
(que é muito claro e simples, mas pode colidir com o _ = gettext.gettext
usado em muitos aplicativos que usam tradução)
Variante 2 (nome fictício)
a, unused, unused = foo()
(acho que não muito atraente, o mesmo vale para outros nomes como dummy
)
Variante 3 (índice)
a = foo()[0]
(para mim os ()[0]
olhares não pitônicos…)
python
coding-style
user49643
fonte
fonte
a, b = foo()[0:2]
funcionaria? Se sim: sim, ele faz :) #a, *_ = foo()
jogará fora todos os valores, exceto o primeiro.Respostas:
Usar o sublinhado para variáveis não utilizadas é definitivamente aceitável. Porém, esteja avisado que, em algumas bases de código, não é uma opção, pois esse identificador está reservado como abreviação para
gettext
. Essa é a objeção mais frequente a esse estilo (embora não seja um problema para a maioria, tanto quanto eu possa julgar). Eu ainda recomendo e sempre o uso sozinho.Os nomes gostam
dummy
ouunused
tendem a me irritar pessoalmente, e eu não os vejo muito frequentemente (em Python, isto é - eu conheço uma base de código Delphi que usadummy
liberalmente, e também vazou para scripts associados ao programa em questão). Eu o aconselharia contra.Também é bom extrair um item da tupla retornada. Ele também evita alguns problemas ao acertar o número de valores não utilizados. Observe que ele tem duas desvantagens em potencial:
fonte
Pylint me adquiriu o hábito de fazê-lo desta maneira:
Ou seja, resultados não utilizados têm um nome descritivo prefixado por _. O Pylint considera os locais prefixados com _ como não utilizados e os globais ou atributos prefixados com _ como privados.
fonte
Se em todo o seu projeto, você estiver fazendo isso apenas uma vez ou muito raramente na função específica, eu usaria a variante 1 se você
gettext
não souber que há um problema nesse módulo e, caso contrário, a variante 3.Por outro lado, se você estava fazendo muito isso - e especialmente se toda vez que quiser um subconjunto diferente dos valores de retorno (criar um invólucro para retornar apenas aqueles inviáveis), pode ser benéfico escrever um invólucro que coloca os resultados em uma tupla nomeada ou em uma instância de outra classe descritiva, o que permitiria:
E então trabalhe com
bar.a
,bar.b
ebar.c
.fonte
Como outros já disseram, underscore (
_
) é o padrão. Mas se o sublinhado estiver sendo usado para traduções, acho que o sublinhado duplo é a melhor alternativa.var, __, value = "VAR=value".partition('=')
Melhor que estes:
var, unused, value = "VAR=value".partition('=')
var, unused_del, value = "VAR=value".partition('=')
var, _del, value = "VAR=value".partition('=')
fonte
Eu não sou um programador Python, mas para mim a terceira variante faz mais sentido.
Na variante 3, você é absolutamente claro com quais valores você está interessado em lidar. Nas variantes 1 e 2, você está atribuindo os valores de volta às variáveis e, portanto, elas podem ser usadas. Você pode tê-los nomeado obscuramente, mas a má nomeação não é realmente uma solução para nenhum problema.
Além da clareza, por que você deseja atribuir valores não utilizados a um slot na memória (como nas variantes 1 e 2)? Essa seria uma solução ruim em termos de gerenciamento de memória.
fonte
Aqui está uma regra geral: se apenas 1 dos valores retornados for usado, por que não simplesmente retornar esse 1 valor? Caso o sinalizador esteja sendo chamado de vários locais, mantenha um sinalizador para o mesmo e retorne valores conforme o sinalizador.
EDITAR:
No caso de você estar na sua situação e não ter escrito a função, talvez eu vá para a Variante 2. Eu manteria os nomes fictícios lá para que os parâmetros possam ser usados em caso de necessidade. Cortar uma lista terá um pouco de sobrecarga. Talvez você possa poupar alguns bytes para receber os dados indesejados.
fonte
%timeit a, _, _ = foo()
vs. o%timeit a = foo()[0]
que resultou em 123ns vs. 109ns, ou seja, o fatiamento parece ser realmente mais rápido que o valor descompactado. Ou você tinha alguma situação específica em mente?