Isso é bastante complicado, mas estou tentando aprender / entender programação funcional em python. O código a seguir:
foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3]
def maptest(foo, bar):
print foo, bar
map(maptest, foos, bars)
produz:
1.0 1
2.0 2
3.0 3
4.0 None
5.0 None
P. Existe uma maneira de usar map ou qualquer outra ferramenta funcional em python para produzir o seguinte sem loops, etc.
1.0 [1,2,3]
2.0 [1,2,3]
3.0 [1,2,3]
4.0 [1,2,3]
5.0 [1,2,3]
Apenas como uma observação lateral, como a implementação mudaria se houvesse uma dependência entre foo e bar. por exemplo
foos = [1.0,2.0,3.0,4.0,5.0]
bars = [1,2,3,4,5]
e imprima:
1.0 [2,3,4,5]
2.0 [1,3,4,5]
3.0 [1,2,4,5]
...
PS: Sei como fazê-lo ingenuamente usando if, loops e / ou geradores, mas gostaria de aprender como obter o mesmo usando ferramentas funcionais. É apenas um caso de adicionar uma instrução if ao maptest ou aplicar outro mapa de filtro às barras internamente no maptest?
python
dictionary
functional-programming
EUSOU brasileiro
fonte
fonte
Respostas:
A maneira mais fácil seria não passar
bars
pelas diferentes funções, mas acessá-lo diretamente demaptest
:Com sua
maptest
função original , você também pode usar uma função lambda emmap
:fonte
Você conhece outras linguagens funcionais? ou seja, você está tentando aprender como o python faz a programação funcional, ou você está tentando aprender sobre a programação funcional e usando o python como veículo?
Além disso, você entende a compreensão da lista?
é diretamente equivalente (*) a:
Na verdade, acho que
map()
antes a remoção do python 3.0 estava programada como redundante (isso não aconteceu).é basicamente equivalente a:
(há uma diferença em como ele lida com o caso em que as seqüências são de comprimento diferente. Como você viu,
map()
preenche Nenhum quando uma das seqüências acaba, enquantozip()
para quando a sequência mais curta é interrompida)Portanto, para abordar sua pergunta específica, você está tentando produzir o resultado:
Você pode fazer isso escrevendo uma função que pega um único argumento e o imprime, seguido por barras:
Como alternativa, você pode criar uma lista parecida com esta:
e use seu maptest original:
Uma maneira de fazer isso seria criar explicitamente a lista de antemão:
Como alternativa, você pode puxar o
itertools
módulo.itertools
contém muitas funções inteligentes que ajudam a executar a programação de avaliação lenta no estilo funcional em python. Nesse caso, queremositertools.repeat
, que produzirá seu argumento indefinidamente à medida que você iterar sobre ele. Este último fato significa que se você fizer:você obterá uma saída sem fim, pois
map()
continua enquanto um dos argumentos ainda estiver produzindo saída. No entanto,itertools.imap
é comomap()
, mas para assim que o menor iterável para.Espero que isto ajude :-)
(*) É um pouco diferente no python 3.0. Lá, map () essencialmente retorna uma expressão de gerador.
fonte
itertools.imap(f, sequence1, sequence2)
é realmente equivalente a[f(x1, x2) for x1, x2 in zip(sequence1, sequence2)]
?list(itertools.imap(f, sequence1, sequence2))
Aqui está a solução que você está procurando:
Eu recomendo o uso de uma compreensão de lista (a
[(x, bars) for x in foos]
parte) sobre o uso do mapa, pois evita a sobrecarga de uma chamada de função em todas as iterações (o que pode ser muito significativo). Se você for usá-lo em um loop for, obterá melhores velocidades usando a compreensão de um gerador:A diferença é que a compreensão do gerador é carregada preguiçosamente .
ATUALIZAÇÃO Em resposta a este comentário:
Suponho que este é um ponto válido. Existem duas soluções para isso que posso pensar. O mais eficiente é provavelmente algo como isto:
Como as tuplas são imutáveis, isso impedirá que as barras sejam modificadas pelos resultados desta compreensão da lista (ou compreensão do gerador, se você seguir esse caminho). Se você realmente precisar modificar todos e cada um dos resultados, poderá fazer o seguinte:
No entanto, isso pode ser um pouco caro, tanto em termos de uso da memória quanto em velocidade, portanto, eu recomendaria isso, a menos que você realmente precise adicionar a cada um deles.
fonte
A programação funcional é sobre a criação de código sem efeitos colaterais.
map é uma abstração de transformação de lista funcional. Você o usa para pegar uma sequência de algo e transformá-lo em uma sequência de algo mais.
Você está tentando usá-lo como um iterador. Não faça isso. :)
Aqui está um exemplo de como você pode usar o mapa para criar a lista que deseja. Existem soluções mais curtas (eu usaria apenas compreensões), mas isso ajudará você a entender o que o mapa faz um pouco melhor:
Observe que, neste ponto, você fez apenas uma manipulação de dados. Agora você pode imprimi-lo:
- Não sei bem o que você quer dizer com 'sem loops'. O FP não é para evitar loops (você não pode examinar todos os itens de uma lista sem visitar cada um). Trata-se de evitar efeitos colaterais, escrevendo menos erros.
fonte
fonte
fonte
Aqui está uma visão geral dos parâmetros para a
map(function, *sequences)
função:function
é o nome da sua função.sequences
é qualquer número de sequências, que geralmente são listas ou tuplas.map
iterará sobre eles simultaneamente e fornecerá os valores atuaisfunction
. É por isso que o número de sequências deve ser igual ao número de parâmetros da sua função.Parece que você está tentando repetir alguns dos
function
parâmetros, mas mantém os outros constantes e, infelizmentemap
, não suporta isso. Encontrei uma proposta antiga para adicionar esse recurso ao Python, mas a construção do mapa é tão limpa e bem estabelecida que duvido que algo assim jamais seja implementado.Use uma solução alternativa, como variáveis globais ou compreensões de lista, como outros sugeriram.
fonte
Isso faria isso?
fonte
bar
implica que ele está recebendo um valor iterado, quando você realmente deseja a lista inteira.Que tal agora:
fonte