As funções lambda têm sido um método de pro­gra­ma­ção funcional desde o Python 1.0. En­tre­tanto, nos últimos anos, outras técnicas ganharam mais po­pu­la­ri­dade e subs­ti­tuí­ram am­pla­mente os lambdas. No entanto, ainda há alguns usos es­pe­ci­a­li­za­dos para lambdas que os pro­gra­ma­do­res ex­pe­ri­en­tes em Python devem conhecer.

O que são funções lambda em Python?

Em Python, a função lambda refere-se a uma função anônima. O Python usa a lambda palavra-chave para criar uma função lambda. Uma expressão lambda consiste na palavra-chave lambda seguida de uma lista de ar­gu­men­tos, dois pontos e uma única expressão. A expressão é fornecida com os ar­gu­men­tos e avaliada quando a função lambda é chamada:

lambda argument: expression

As funções são uma cons­tru­ção de linguagem fun­da­men­tal em quase todas as lin­gua­gens de pro­gra­ma­ção e re­pre­sen­tam a menor unidade reu­ti­li­zá­vel de código. Nor­mal­mente, as funções em Python são definidas com a def palavra-chave. Como exemplo, mos­tra­re­mos a função square que mul­ti­plica um número por ele mesmo:

# Define square function
def square(num):
    return num * num
# Show that it works
assert square(9) == 81
python

A def palavra-chave é uma forma bem conhecida de definir funções em Python, mas a linguagem também tem lambdas. Essas são funções anônimas que definem uma expressão com pa­râ­me­tros. As lambdas podem ser usadas em qualquer lugar em que uma função seja esperada ou possa ser atribuída a um nome. Você pode ver a expressão lambda equi­va­lente à função square aqui:

# Create square function
squared = lambda num: num * num
# Show that it works
assert squared(9) == 81
python
Nota

Em Python, a função lambda refere-se a uma função criada com a palavra-chave lambda . Lambda não é o nome de uma função es­pe­cí­fica nem é um dos ope­ra­do­res Python.

Qual é a diferença entre lambda e def?

Pode parecer estranho que o Python permita que você crie funções com ambos os termos lambda e def. No entanto, Lambda não é um recurso próprio **, mas apenas outra forma de criar funções curtas lo­cal­mente. Toda função criada com lambda também pode ser criada com def. No entanto, esse não é o caso inverso.

No nível sintático, lambda e def são ambas palavras-chave. Uma diferença im­por­tante entre elas é a separação rígida entre de­cla­ra­ção e expressão do Python ****. As de­cla­ra­ções são etapas na execução do código, enquanto as ex­pres­sões são avaliadas em um valor.

Def inicia uma instrução ou, mais es­pe­ci­fi­ca­mente, uma instrução composta, que contém outras ins­tru­ções. Somente return de­cla­ra­ções podem aparecer em uma def de­cla­ra­ção. Um return statement retorna um valor quando a função definida com def é chamada.

Ao contrário da def statement, lambda inicia uma expressão que não pode conter nenhuma instrução. A expressão lambda recebe um ou mais ar­gu­men­tos e retorna uma função anônima. Quando a função lambda é chamada, a expressão contida nela é avaliada com os ar­gu­men­tos passados e é retornada.

Quais são as li­mi­ta­ções das ex­pres­sões lambda do Python?

O Python limitou pro­po­si­tal­mente a utilidade das funções lambda, pois ge­ral­mente é melhor nomear as funções. Isso força os pro­gra­ma­do­res a pensar sobre o sig­ni­fi­cado da função e a dis­tin­guir cla­ra­mente as partes.

Os lambdas não podem conter ins­tru­ções, ao contrário do corpo de uma função definida com a def palavra-chave. Portanto, não é possível usar , if, for, etc. em uma função lambda. Também não é possível acionar uma exceção, pois isso requer uma de­cla­ra­ção.

As funções lambda em Python podem conter uma única expressão que é avaliada quando chamada. Anotações de tipo não podem ser usadas dentro da expressão lambda. Atu­al­mente, a maioria dos casos de uso de funções lambda em Python utiliza outras técnicas, como com­pre­en­sões.

Di­fe­ren­tes usos das funções lambda em Python

As lambdas são derivadas da pro­gra­ma­ção funcional. Em algumas lin­gua­gens, como Ja­vaS­cript, as funções anônimas são am­pla­mente usadas sem a ne­ces­si­dade de uma palavra-chave especial. No Python, as ex­pres­sões lambda são usadas para criar pequenas funções lo­cal­mente. Veremos suas apli­ca­ções mais úteis a seguir.

Como preencher funções de ordem superior em Python com lambdas

Os lambdas são fre­quen­te­mente usados com funções de ordem superior como map(), filter() e reduce(). Os elementos de um iterável podem ser trans­for­ma­dos sem o uso de loops graças aos lambdas. As funções de ordem superior são funções que recebem funções como pa­râ­me­tros ou retornam uma função.

A função map() recebe uma função e um iterável como pa­râ­me­tros. Ela executa a função para cada elemento do iterável. Vamos tentar gerar números quadrados. Usamos a map() função e passamos uma expressão lambda como argumento, o que gera a função square. A função quadrada é aplicada a cada elemento da lista com map():

nums = [3, 5, 7]
# Square numbers using `map()` and `lambda`
squares = map(lambda num: num ** 2, nums)
# Show that it works
assert list(squares) == [9, 25, 49]
python
Nota

A partir do Python 3.0, as funções map() e filter() retornam um iterável em vez de uma lista. Uma list() chamada é usada dentro das assert de­cla­ra­ções para de­sem­pa­co­tar iteráveis em uma lista.

As com­pre­en­sões de lista oferecem uma abordagem mais moderna para o pro­ces­sa­mento de iteráveis. Em vez de recorrer a map() e gerar uma função lambda, podemos descrever a operação di­re­ta­mente:

nums = [3, 5, 7]
# Square numbers using list comprehension
squares = [num ** 2 for num in nums]
# Show that it works
assert squares == [9, 25, 49]
python

A filter() função pode ser usada para filtrar os elementos de um iterável. Podemos estender nosso exemplo para gerar somente números quadrados pares:

# List of numbers 1-4
nums = [1, 2, 3, 4]
# Square each number
squares = list(map(lambda num: num ** 2, nums))
# Filter out the even squares
even_squares = filter(lambda square: square % 2 == 0, squares)
# Show that it works
assert list(even_squares) == [4, 16]
python

Mostramos a abordagem preferida de usar a com­pre­en­são de lista para gerar o mesmo resultado sem usar lambdas e funções de ordem superior. A if parte da com­pre­en­são é usada para filtrar os números pares dos números quadrados gerados:

# List of numbers 1-4 squared
squares = [num ** 2 for num in range(1, 5)]
# Filter out the even squares
even_squares = [square for square in squares if square % 2 == 0]
# Show that it works
assert even_squares == [4, 16]
python
Nota

A função reduce() do Python não foi incluída na bi­bli­o­teca padrão desde o Python 3.0. Essa função pode ser en­con­trada no functools módulo.

Como im­ple­men­tar funções-chave em Python com lambdas

As com­pre­en­sões subs­ti­tuí­ram am­pla­mente as funções clássicas de ordem superior map() e filter() no Python. No entanto, as funções-chave podem ser usadas para de­mons­trar todos os pontos fortes dos lambdas.

As funções de com­pa­ra­ção do Python sorted(), min() e max() operam em iteráveis. Cada elemento do iterável é submetido a uma com­pa­ra­ção quando chamado. As três funções recebem uma função-chave como parâmetro opcional. A função de chave é chamada para cada elemento e retorna um valor de chave para a operação de com­pa­ra­ção.

Vamos con­si­de­rar o seguinte problema. Temos uma pasta com arquivos de imagem em que os nomes são mapeados para uma lista Python. Queremos clas­si­fi­car a lista. Todos os nomes de arquivos começam com img, seguido de um número:

# List of image file names
images = ['img1', 'img2', 'img30', 'img3', 'img22', 'img100']
python

Se usarmos a função sorted() do Python, a ordem le­xi­co­grá­fica será usada. Isso trata os dígitos con­se­cu­ti­vos como números únicos. Assim, os números ['1', '2', '100'] são colocados na ordem ['1', '100', '2']. O resultado não é o esperado:

# Sort using lexicographic order
sorted_image = sorted(images)
# Show that it works
assert sorted_image == ['img1', 'img100', 'img2', 'img22', 'img3', 'img30']
python

Nós passamos uma lambda expressão que produz uma função-chave para garantir que a clas­si­fi­ca­ção esteja correta. A função key extrai a parte numérica de um nome de arquivo, que é usada como uma chave por sorted():

# Extract numeric component and sort as integers
sorted_image = sorted(images, key=lambda name: int(name[3:]))
# Show that it works
assert sorted_image == ['img1', 'img2', 'img3', 'img22', 'img30', 'img100']
python

A função de chave é usada lo­cal­mente e apenas uma vez. Não é ne­ces­sá­rio definir uma função nomeada extra para ela. Lambdas são a maneira correta de criar funções-chave. Vamos dar uma olhada em mais dois exemplos.

Assim como sorted(), as funções in­te­gra­das do Python min() e max() têm uma função-chave opcional. As funções localizam o menor e o maior elemento em uma lista ou outro iterável. O menor ou maior elemento é uma questão de definição e pode ser es­pe­ci­fi­cado usando a função key.

Está claro o que significa o menor ou o maior elemento para listas de valores simples, como uma lista de números. Não pre­ci­sa­mos de uma função-chave especial nesse caso:

nums = [42, 69, 51, 13]
assert min(nums) == 13
assert max(nums) == 69
python
Nota

Se nenhuma função de chave for passada, a função de iden­ti­dade f(x) = x será usada como padrão. Isso pode ser fa­cil­mente definido como um lambda Python com lambda x: x.

Mas e se cada elemento de um iterável incluir várias datas? Vamos imaginar uma lista de ditados que re­pre­sen­tam pessoas com seus nomes e idades. Qual é o critério para min() e max() decidir qual é o menor e o maior elemento? É nesse ponto que uma função-chave é útil.

Pre­ci­sa­mos de dados de exemplo para ilustrar como as funções-chave funcionam. Vamos criar uma função Person() que sirva como um cons­tru­tor:

# Constructor function for dict representing a person
def Person(name, age):
    return {'name': name, 'age': age}
# Check that it works as expected
assert Person('Jim', 42) == {'name': 'Jim', 'age': 42}
python

Nós criamos uma lista de pessoas usando nossa função cons­tru­tora:

# Create list of people
people = [person('Jim', 42), person('Jack', 51), person('John', 69)]
python

En­con­tra­mos a pessoa mais velha usando a max() chamada. Isso gera uma função-chave usando a expressão lambda, que recebe um dict de pessoa e extrai a idade dele como um elemento de com­pa­ra­ção:

# Find the oldest person
oldest = max(people, key=lambda person: person['age'])
# Check that it works
assert oldest == Person('John', 69)
python

A abordagem funciona exa­ta­mente da mesma forma para a função min() . Nesse caso, vamos definir a função-chave fora da min() chamada e usar uma expressão lambda novamente. Isso melhora a le­gi­bi­li­dade e vale a pena se a função-chave tiver vários usos locais:

# Define key function to compare people by age
by_age = lambda person: person['age']
# Find the youngest person
youngest = min(people, key=by_age)
# Check that it works
assert youngest == Person('Jim', 42)
python

Como criar closures com lambdas Python

Os lambdas do Python também são usados para definir closures. São funções criadas por outras funções e que armazenam um valor. As closures podem ser uti­li­za­das para criar famílias de funções se­me­lhan­tes. Mos­tra­re­mos um exemplo comum em que são criadas funções de potência.

As funções de potência recebem um argumento e o ex­po­nen­ciam. A função quadrada f(x) = x ^ 2 e a função cúbica f(x) = x ^ 3 são exemplos bem co­nhe­ci­dos. Funções de potência ar­bi­trá­rias podem ser geradas como fe­cha­men­tos usando uma função cons­tru­tora. Usaremos uma expressão lambda, o que significa que não pre­ci­sa­mos definir uma função interna nomeada:

# Define constructor function for power functions
def power(n):
    return lambda num: num ** n
# Create square and cubic functions as closures
square = power(2)
cubic = power(3)
# Show that it works
assert square(10) == 100
assert cubic(10) == 1000
python

Como usar a expressão de função ime­di­a­ta­mente invocada (IIFE) com lambdas Python

O IIFE, pro­nun­ci­ado “iffy”, é um padrão conhecido em Ja­vaS­cript. Ele envolve a definição de uma função anônima e sua execução imediata.

Lambdas podem ser usados como IIFEs, embora não sejam muito úteis devido às li­mi­ta­ções do Python. Só pre­ci­sa­mos colocar pa­rên­te­ses ao redor da expressão lambda:

(lambda num: num * num)
python

E outro par de pa­rên­te­ses contendo o argumento(s):

assert (lambda num: num * num)(3) == 9
python
Dica

Para ini­ci­an­tes em Python, re­co­men­da­mos dar uma olhada em nosso Tutorial de Python.

Ir para o menu principal