Alguém pode explicar as razões concretas pelas quais a BDFL escolhe criar lambdas em Python em uma única linha?
Isso é bom:
lambda x: x**x
Isso resulta em um erro:
lambda x:
x**x
Entendo que a criação de várias linhas lambda de alguma forma "perturbaria" as regras normais de indentação e exigiria a adição de mais exceções, mas isso não vale os benefícios?
Veja o JavaScript, por exemplo. Como alguém pode viver sem essas funções anônimas? Eles são indispensáveis. Os Pythonistas não querem se livrar de ter que nomear todas as funções de várias linhas apenas para passar isso como argumento?
def
? Agora ele tem exatamente a mesma estrutura visual.Respostas:
Guido van van Rossum respondeu:
http://www.artima.com/weblogs/viewpost.jsp?thread=147358
Basicamente, ele diz que, embora uma solução seja possível, ela não é congruente com a forma como o Python é.
fonte
é perfeitamente bom fazer um lambda de várias linhas em python: veja
a limitação real do lambda é o fato de que lambda deve ser uma expressão única ; não pode conter palavras-chave (como python2
print
oureturn
).O GvR decide fazer isso para limitar o tamanho do lambda, pois eles normalmente são usados como parâmetros. Se você deseja uma função real, use
def
fonte
def
. Pense bem: você realmente precisa de um código de chamada como parâmetro de sua função? E os usuários dessa função não têm permissão para transmitir seu valor padrão que pode ser chamado? Como eles podem passar se você não dá a eles?Eu sei que isso é super antigo, mas colocando aqui como referência.
Uma alternativa ao uso do lambda poderia ser o uso de um
def
modo não convencional. O objetivo é passar adef
para uma função, o que pode ser feito em apenas uma circunstância - um decorador. Observe que com essa implementaçãodef result
não cria uma função, ele cria o resultado dereduce()
, que acaba sendo adict
.Plugue sem vergonha : faço muito isso aqui .
Observe que lambdas com várias instruções podem ser feitas, mas apenas com código muito, muito feio. No entanto, o interessante é como o escopo funciona com essa implementação (observe o uso múltiplo da
name
variável e o sombreamento damessage
variável.fonte
Hackear um lambda com várias instruções não é tão ruim quanto a pyrospade: certamente poderíamos compor um monte de funções monádicas usando o bind, como em Haskell, mas como estamos no mundo impuro do Python, podemos também use efeitos colaterais para conseguir a mesma coisa.
Cubro algumas maneiras de fazer isso no meu blog .
Por exemplo, o Python garante avaliar os elementos de uma tupla em ordem, para que possamos usar
,
como um imperativo;
. Podemos substituir muitas declarações, comoprint
, por expressões, comosys.stdout.write
.Portanto, o seguinte é equivalente:
Observe que eu adicionei um
None
no final e o extraí usando[-1]
; isso define o valor de retorno explicitamente. Não precisamos fazer isso, mas sem ele obteríamos um(None, None, None)
valor de retorno desagradável , com o qual podemos ou não nos importar.Para que possamos sequenciar as ações de IO. E as variáveis locais?
Como o Python
=
forma uma declaração, precisamos encontrar uma expressão equivalente. Uma maneira é alterar o conteúdo da estrutura de dados, transmitida como argumento. Por exemplo:Existem alguns truques sendo usados em
stateful_lambda
:*_
argumento permite que o nosso lambda aceite qualquer número de argumentos. Como isso permite zero argumentos, recuperamos a convenção de chamada destateful_def
._
é apenas uma convenção que diz "Não vou usar essa variável"lambda state: lambda *_: ...
(lambda state: ...)({})
state
a um valor{}
sem usar uma declaração de atribuição (por exemplo,state = {}
)state
como nomes de variáveis e valores vinculadosstate.setdefault(a, b)
vez dea = b
e emstate.get(a)
vez dea
[-1]
para extrair o último valor, que age como umareturn
declaraçãoClaro que isso é bastante complicado, mas podemos criar uma API melhor com funções auxiliares:
fonte
Embora eu possa contribuir, use um disjuntor de linha:
Não esqueça a coisa muito agradável que python é capaz de escrever oneliners, como no exemplo:
E o lambda é muito poderoso, mas não se destina à substituição de uma função inteira, quero dizer que você pode hacká-lo como (exemplo de empréstimo do colega acima):
Mas você realmente quer fazer assim? É quase ilegível depois de algum tempo, é como chegar ao início da corda, começando com o fim desvendado.
As lambdas são usadas como funções únicas, no mapa, filtram e reduzem funções na Programação Orientada a Funcionalidade (entre outras coisas). Por exemplo, obter valores de caracteres de números inteiros e divisíveis por 2
Você pode usá-lo como função de expressão de função, alterando a função complexa (ou mais e várias lambdas e colocando-a dentro de outra lambda:
mas o Python tem suporte a expressões de função de outra maneira: -vemos que você tem alguma função chamada
superAwesomeFunction
e essa função pode fazer coisas super impressionantes, você pode atribuí-lo a uma variável sem chamá-lo, assim:Então agora, quando você chama SAF, chama superAwesomeFunction ou método. Se você pesquisar na sua pasta Lib, poderá descobrir que a maioria dos
__builtin__
módulos python é escrita dessa maneira. Isso é feito porque, às vezes, você precisará de algumas funções que executam tarefas específicas que não são necessárias o suficiente para serem utilizadas pelo usuário, mas que são necessárias para várias funções. Então, você pode optar por não ter 2 funções com o nome "superAwesomeFunction", pode ter "superAwesomeFunctionDoingBasicStuf" e "realSuperAwesomeFunction" e, em seguida, basta colocar a variável "realSuperAwesomeFunction" na variável "superAwesomeFunction" e pronto.Você pode encontrar a localização dos módulos importados digitando no console
importedModule.__file__
(exemplo realimport os;os.__file__
) e basta seguir esse diretório para o arquivo chamado ImportModule.py e abri-lo no editor e descobrir como você pode maximizar seu próprio "conhecimento".Espero que isso ajude você e talvez outros colegas com problemas.
fonte