Python Iluminado

Expressões Lambda

Expressões lambda também são conhecidas como funções anônimas, elas diferem das funções comuns por serem declaradas de maneira diferente, sem definirmos nome para criarmos elas, utilizamos a palavra-chave lambda para definí-las.

Python e outras linguagens como Java, C# e até mesmo C++ tiveram as funções lambda adicionadas a sua sintaxe, já linguagens como LISP, ou linguagens da família ML: Haskell, OCaml e F# usam lambdas como um conceito central.

Expressões Lambda em Python e em outras linguagens de programação possuem suas raízes no cálculo lambda, um modelo de computação inventando por Alonzo Church.

O cálculo lambda pode codificar qualquer cálculo, é Turing completo, mas ao contrário do conceito de máquina de Turing, é puro e não guarda nenhum estado.

As linguagens funcionais têm sua origem na lógica matemática e no cálculo lambda, enquanto as linguagens de programação imperativas adotam o modelo de computação baseado em estado inventado por Alan Turing. Os dois modelos de computação, cálculo lambda e máquinas de Turing, podem ser traduzidos um no outro. Essa equivalência é conhecida como hipótese de Church-Turing.

As linguagens funcionais herdam diretamente a filosofia do cálculo lambda, adotando uma abordagem declarativa de programação que enfatiza a abstração, a transformação de dados, a composição e a pureza (sem estado e sem efeitos colaterais). Exemplos de linguagens funcionais incluem Haskell e Lisp.

  • Expressões lambdas podem receber qualquer número de argumentos, porém retornam apenas um valor na forma de expressão, elas não podem ter comandos ou multiplas expressões
  • Uma função anônima não pode ser chamada diretamente pela função print(), pois ela requer uma expressão

Funções Anônimas

Os seguintes termos são usados de forma de forma intercambiável dependendo da linguagem de programação ou local que você vive:

  • Funções Anônimas
  • Funções Lambda
  • Expressões Lambda
  • Abstrações Lambda
  • Forma Lambda
  • Literais de Função

Fundamentos Básicos

img

A estrutura para utilizarmos as funções lambdas é muito simples

lambda argumento1, argumento2, argumento3: expressão

Por exemplo, se quisermos multiplicar o argumento por 3:

triplo = lambda x: x * 3
print(type(triplo)) # <class 'function'>
print(triplo(3)) # 9

Se quisermos elevar o número ao quadrado:

quadrado = lambda x: x * x
print(quadrado(5)) # 25

As expressões lambdas também nos permitem trabalharmos com strings, por exemplo:

nome_completo = lambda nome,sobrenome: f'Nome: {nome.title()}\nSobrenome: {sobrenome.title()}'
print(nome_completo('isaac','newton'))
# Nome: Isaac
# Sobrenome: Newton

Podemos também usar condicionais com funções Lambda

comeca_com_G = lambda x: True if x.startswith('G') else False
print(comeca_com_G('Gabriel')) # True
print(comeca_com_G('Rafael')) # False

Se quisermos verificar se um determinado número é ímpar:

impar = lambda x: True if x % 2 == 1 else False
print(impar(1)) # True
print(impar(8)) # False

Até mesmo compor funções mais complexas, neste caso, imprimir a palavra que vem antes da palavra passada via argumento.

palavra_antes = lambda s, w: s.split()[s.split().index(w)-1] if w in s else None
sentenca = 'Rato Roeu Roupa Rei Roma'
print(palavra_antes(sentenca,'Roma')) # Rei

Lambda em Python

Nós normalmente usamos as funções Lambda quando precisamos de uma função por um período curto de tempo, podemos também usá-las como argumentos para funções de high-order (funções que recebem outras funções como argumento).

Funções lambda também podem ser usadas com outras funções pré-construídas, como filter(), map(), etc.

Filtrando

Por exemplo, com filter(), que recebe uma função e uma lista como argumento.

lista = [1,2,3,4,5]
nova_lista = list(filter(lambda x: (x % 2 == 0), lista))
print(nova_lista) # [2, 4]

Veja que a expressão lambda calculará o resto de divisão de cada valor da lista, caso o valor seja 0 o número será filtrado para nossa nova lista, formando assim uma lista de números pares.

Mapeando

Por exemplo, com map(), que também recebe uma função e uma lista como argumento.

lst = [3,5,6,7,9]
nova_lst = list(map(lambda y: y * 10, lst))
print(nova_lst) # [30, 50, 60, 70, 90]

Dessa vez a expressão lambda multiplicará cada item da lista por 10 e estes serão mapeados em uma nova lista.

Podemos usar esta ideia para converter de uma lista de temperaturas em grau Celsius para grau Fahrenheit.

celsius = [31.5, 22.1, 17.5, 42.8]
fahrenheit = map(lambda x: (float(9)/5)*x + 32, celsius)
print(list(fahrenheit)) # [88.7, 71.78, 63.5, 109.03999999999999]

Ordenando

Através do método sort() podemos por exemplo organizar uma lista com uma expressão lambda. Vejamos um exemplo para ilustrar esta ideia:

alimentos = [('ovos', 10),('pães', 5),('tomate', 6),('cenoura', 4),('maçã', 3)]

Ordenando os alimentos por ordem alfabética:

alimentos.sort(key = lambda x: x[0])
print(alimentos)
# [('cenoura', 4), ('maçã', 3), ('ovos', 10), ('pães', 5), ('tomate', 6)]

Ordenando os alimentos por quantidade crescente:

alimentos.sort(key = lambda x: x[1])
print(alimentos)
# [('maçã', 3), ('cenoura', 4), ('pães', 5), ('tomate', 6), ('ovos', 10)]

Obtendo o alimento com a maior quantidade:

print(max(alimentos, key = lambda x: x[1])) # ('ovos', 10)

Obtendo o alimento com a menor quantidade:

print(min(alimentos, key = lambda x: x[1])) # ('maçã', 3)

Função que cria Funções

É possível criarmos uma função que nos retorna uma expressão lambda para assim realizarmos cálculos:

# Função que cria funções
def construcao_quadraticas(a, b, c):
"""Retorna a função f(x) = ax^2 + bx + c"""
return lambda x: a*x**2 + b*x + c
# Constrói uma nova função com os parâmetros (4,7,-6)
f = construcao_quadraticas(4,7,-6)
print(f(0)) # -6
print(f(3)) # 51

Muito legal e útil, não? Expressões lambdas podem agilizar bastante nossa vida.