Considere o seguinte código python2
In [5]: points = [ (1,2), (2,3)]
In [6]: min(points, key=lambda (x, y): (x*x + y*y))
Out[6]: (1, 2)
Isso não é compatível com python3 e tenho que fazer o seguinte:
>>> min(points, key=lambda p: p[0]*p[0] + p[1]*p[1])
(1, 2)
Isso é muito feio. Se o lambda fosse uma função, eu poderia fazer
def some_name_to_think_of(p):
x, y = p
return x*x + y*y
Remover esse recurso em python3 força o código a fazer o caminho feio (com índices mágicos) ou a criar funções desnecessárias (a parte mais incômoda é pensar em bons nomes para essas funções desnecessárias)
Acho que o recurso deve ser adicionado de volta pelo menos para lambdas sozinho. Existe uma boa alternativa?
Atualização: estou usando o seguinte auxiliar, estendendo a ideia na resposta
def star(f):
return lambda args: f(*args)
min(points, key=star(lambda x,y: (x*x + y*y))
Update2: uma versão mais limpa parastar
import functools
def star(f):
@functools.wraps(f):
def f_inner(args):
return f(*args)
return f_inner
python
python-3.x
Balki
fonte
fonte
lambda
que seja removido da linguagem completamente do que reverter as alterações que a tornaram mais difícil de usar, mas você pode tentar postar em ideias-python se quiser expressar o desejo de ver o recurso adicionado de volta.lambda
no mesmo espírito que ele se opõemap
,reduce
efilter
.lambda
foi programado para remoção no py3k, pois é basicamente uma praga na linguagem. Mas ninguém conseguia chegar a um acordo sobre uma alternativa adequada para definir funções anônimas, então, eventualmente, Guido jogou as armas na derrota e foi isso.map
efilter
sejam melhor substituídos por compreensões, eu gostoreduce
)Respostas:
Não, não há outra maneira. Você cobriu tudo. O caminho a seguir seria levantar essa questão na lista de discussão de ideias do Python , mas esteja preparado para discutir muito lá para ganhar um pouco de força.
Na verdade, só para não dizer "não há saída", uma terceira maneira poderia ser implementar mais um nível de chamada lambda apenas para desdobrar os parâmetros - mas isso seria ao mesmo tempo mais ineficiente e mais difícil de ler do que suas duas sugestões:
atualizar Python 3.8
A partir de agora, o Python 3.8 alpha1 está disponível e as expressões de atribuição PEP 572 estão implementadas.
Então, se alguém usa um truque para executar várias expressões dentro de um lambda - geralmente faço isso criando uma tupla e apenas retornando o último componente dela, é possível fazer:
Deve-se ter em mente que esse tipo de código raramente será mais legível ou prático do que ter uma função completa. Ainda assim, há usos possíveis - se houver vários one-liners que operariam nisso
point
, pode valer a pena ter um namedtuple e usar a expressão de atribuição para efetivamente "lançar" a sequência de entrada para o namedtuple:fonte
def
que é mencionado na pergunta sob o nmesome_name_to_think-of
.key = lambda p: (x:=p[0], y:=p[1], x ** 2 + y ** 2)[-1]
De acordo com http://www.python.org/dev/peps/pep-3113/ a descompactação de tupla acabou e
2to3
irá traduzi-la da seguinte forma:Que é bastante semelhante à sua implementação.
fonte
Não conheço nenhuma boa alternativa geral para o comportamento de desempacotamento dos argumentos do Python 2. Aqui estão algumas sugestões que podem ser úteis em alguns casos:
se você não consegue pensar em um nome; use o nome do parâmetro de palavra-chave:
você pode ver se um
namedtuple
torna seu código mais legível se a lista for usada em vários lugares:fonte
lambda (x, y):
elambda x, y:
não é óbvia à primeira vista.Embora os argumentos de desestruturação tenham sido removidos no Python3, eles não foram removidos das compreensões. É possível abusar dele para obter um comportamento semelhante no Python 3. Em essência, aproveitamos o fato de que as co-rotinas nos permitem virar as funções do avesso, e o rendimento não é uma instrução e, portanto, é permitido dentro dos lambdas.
Por exemplo:
Em comparação com a resposta aceita de usar um invólucro, esta solução é capaz de desestruturar completamente os argumentos, enquanto o invólucro destrói apenas o primeiro nível. Isso é,
Em comparação a
Alternativamente, também se pode fazer
Ou um pouco melhor
Isso é apenas para sugerir que isso pode ser feito e não deve ser tomado como uma recomendação.
fonte
Com base na sugestão do Cuadue e em seu comentário sobre o desempacotamento ainda estando presente nas compreensões, você pode usar
numpy.argmin
:fonte
Outra opção é escrevê-lo em um gerador produzindo uma tupla onde a chave é o primeiro elemento. As tuplas são comparadas do início ao fim para que a tupla com o menor primeiro elemento seja retornada. Você pode então indexar no resultado para obter o valor.
fonte
Considere se você precisa descompactar a tupla em primeiro lugar:
ou se você precisa fornecer nomes explícitos ao desempacotar:
fonte
Acho que a melhor sintaxe é
x * x + y * y let x, y = point
, alet
palavra-chave deve ser escolhida com mais cuidado.O lambda duplo é a versão mais próxima.
lambda point: (lambda x, y: x * x + y * y)(*point)
O auxiliar de função de alta ordem seria útil caso lhe atribuíssemos um nome próprio.
fonte