Pesquisa: Funções de Ordem-Superior ( Higher-Order Functions) em Python | Material de Apoio a Aprendizagem |

Higher Order-Functions

"Funções de Ordem-Superior" (HoF - Higher-Order Functions) são descritas como funções que operam em outras funções, seja tomando-as como argumentos ou retornando-as como resultado. HoF também permitem composição de funções, ou seja, possuir pequenas funções que compõem funcionalidades que realizam tarefas mais extensas e complexas. As Funções de Ordem-Superior são componentes que estão cada vez mais presentes nas linguagens de programação modernas tais como Java, Javascript e R.

Funções de Ordem-Superior em Python

As funções de Ordem-Superior, são uma ferramenta poderosa em Python e podem melhorar significativamente como você constroi seus programas, pois tornam o código mais genérico, flexivel e reutilizável. Elas são parte do paradigma de programação funcional, de forma separada e organizada e apenas compor sub-resultados. As HoF são consideradas "cidadãos de primeira classe" e, portanto, podem ser usadas como qualquer outro tipo de valor.


# Higher-Order Functions
#Função que calcula o dobro de um valor 
def  

dobro

(valor)

:

return

2

*

valor

#Função que calcula o quadrado de um valor def

quadrado

(valor)

:

return

valor

*

valor

#Função que calcula o negativo de um valor def

negativo

(valor)

:

return

-

1

*

valor

#Função que aplica a função func ao valor def

mat_func

(func, valor)

:

return

func

(valor)

#Exemplos de Uso print(

mat_func

(

dobro

,

3

)) 6 print(

mat_func

(

quadrado

,

3

)) 9 print(

mat_func

(

negativo

,

3

)) -

3

Propriedades de funções de Ordem-Superior.

Algumas das propriedades mais importantes das funções de Ordem-Superior que são aplicáveis em Python são:

  • Na função de Ordem-Superior, podemos armazenar uma função dentro de uma variável.
  • Uma função pode atuar como uma instância de um tipo de objeto.
  • Na função de Ordem-Superior, podemos retornar uma função como resultado de outra função.
  • Em funções de Ordem-Superior, podemos passar uma função como parâmetro ou argumento dentro de outra função.
  • Podemos armazenar funções de Ordem-Superior do Python em formato de estruturas de dados,como listas, tabelas de hash, etc.

Funções de Ordem-Superior aplicadas a listas vazias.

As funções de ordem superior (HoFs) em Python são ferramentas poderosas que podem ser usadas para processar listas de forma eficiente e concisa. No entanto, é importante considerar o comportamento dessas funções quando aplicadas a listas vazias. Devido à sua natureza recursiva, as HoFs geralmente definem um caso base para lidar com listas vazias, garantindo que a função funcione de maneira consistente, mesmo na ausência de elementos.

Map, Filter e Reduce: as HoF mais utilizadas

Obviamente, você pode construir qualquer tipo de função de Ordem-Superior e acoplá-las em suas funcionalidades. Entretanto, três funções ganharam enorme destaque dentro das abordagens funcionais, tanto que foram incluidas na maioria das linguagens de programação com suporte a comportamento funcional: map, filter e reduce. Vamos investigar cada uma delas em mais detalhes abaixo!

MAP

map(( => ), [ , , ]) = [ , , ]

A HoF MAP possui dois parâmetros: a função de transformação, que é aplicada a cada elemento de uma lista, e a lista a ser mapeada. No exemplo abaixo, a função de mapeamento fornecida é aplicada a cada elemento da lista, um por vês, e o elemento transformado é inserido em uma nova lista, que será o resultado da HoF MAP.

Observe que a HoF MAP é imutável: a lista fornecida como parâmetro não é alterada, e uma nova lista é gerada como resultado do mapeamento. Perceba que a cardinalidade da lista resultado também não se altera: se N elementos estão presentes na lista argumento, a lista resultado também possuirá N elementos.Quando aplicada a uma lista vazia, a HoF MAP geralmente retorna uma lista vazia. Isso ocorre porque não há elementos na lista original para aplicar a função de transformação.

Exemplo 1 Map:


# temperaturas em Fahrenheit 
temp_fahrenheit = [

78, 80, 100, 98

] # função para realizar a conversão de temperatura para Celsius def

celsius

(T)

:

return

round

((

float

(

5

) /

9

) * (T-

32

),

2

) #utilizando a função map para converter cada temperatura da lista

valores

=

list

(

map

(

celsius

,

temp_fahrenheit

)) #Saída print

(valores)

[25.56, 26.67, 37.78, 36.67]

Exemplo 2 Map:


# Listas contendo Siglas de alguns Estados Brasileiros 

EstadosBR

= [

'am','ba','ms','rr','to'

] #utilizando a função map para converter os itens da lista letras maiusculas

EstadosBR

=

list

(

map

(

str.upper

,

EstadosBR

)) #Saída

print

(ESTADOSBR)

['AM','BA','MS','RR','TO']

Exemplo 3 Map:


def 

obter_nome

(email)

: return

email.

split

(

"@"

)[

0

] emails = [

"joaosilva@email.com", "mariagomes@email.com.br", "pedrodutra@email.com"

] nomes =

list

(

map

(

obter_nome

,

emails

)) print

(nomes)

['joaosilva','mariagomes','pedrodutra']

FILTER

filter(( ), [ , , , , ]) = [ , ]

A HoF FILTER testa se cada elemento da lista argumento satisfaz a condição da função parâmetro. Para cada elemento cujo o resultado da função é TRUE, esse elemento é inserido na nova lista de resultado. Portanto, filter retorna um nova lista contendo apenas os elementos que satisfazem a função parâmetro.Quando a lista fornecida como argumento está vazia, a HoF FILTER retorna uma lista vazia.

A HoF FILTER também é imutável: a lista argumento permanece inalterada. Entretanto, a cardinalidade da lista resultado pode variar de 0 a N: se nenhum elemento satisfazer a função de condição, a lista resultado será vazia. Se todos os elementos atendem a função de condição, a lista resultado terá N elementos. Perceba que a função de condição deve avaliar cada elemento da lista, um a um, para um resultado TRUE ou FALSE. Logo, o resultado da função de condição só pode ser Booleana.

Exemplo 1 Filter:


# Criando a função de critério 
def 

maior_que_zero

(numeros)

:

return

numeros

>

0

#Gerando uma lista com valores definidos aleatoriamente

valores

= [

10, 4, -1 , 3, 5, -9 ,-11

] #Aplicando filter na lista com valores

valores

=

list

(

filter

(

maior_que_zero

,

valores

)) #Saída print

(valores)

[ 10, 4, 3, 5 ]

Exemplo 2 Filter:


# Criando a função de critério 
def 

retornaEstado

(x)

:

return

x

startswith

('M')

# Listas contendo Siglas de alguns Estados Brasileiros

ESTADOSBR

= [

'MS','AM','BA','MT','TO','MG'

] # utilizando a função filter para encontrar os estados que iniciam com a letra M

ESTADOSBR

=

list

(

filter

(

retornaEstado

,

EstadosBR

)) #Saída print

(ESTADOSBR)

['MS','MT','MG']

Exemplo 3 Filter:


def 

eh_gmail

(email)

: return

email.

split

(

"@"

)[

1

] ==

"gmail.com"

emails = [

"joaosilva@hotmail.com", "mariagomes@gmail.com", "pedrodutra@outlook.com", "marcos@gmail.com"

]

usuarios_gmail

=

filter

(

eh_gmail

,

emails

) print(

list

(usuarios_gmail)

) ['mariagomes@gmail.com','marcos@gmail.com']

REDUCE

reduce(redutor, [, , , , ], acumulador) = [ ]

A HoF REDUCE, diferentemente das funções MAP e FILTER, não é nativa no Python, e precisa ser importada de alguma biblioteca (functools). O REDUCE também é diferente pois não retorna (necessariamente) uma lista como resultado: ela pode retornar apenas um valor resultante da aplicação da função de redução a todos os elementos da lista.

Para tanto, REDUCE introduz um novo parâmetro que serve como acumulador para o resultado parcial a cada iteração com os elementos da lista.

A HoF REDUCE também é imutável: a lista argumento permanece inalterada. Para simplificar, podemos assumir que a cardinalidade do REDUCE é 1, pois a lista argumento será reduzida a um único elemento resultante. REDUCE combina elementos de uma lista usando uma função binária. Quando a lista fornecida como argumento está vazia, o comportamento do reduce depende do valor do acumulador. Se nenhum valor for fornecido para o acumulador, uma exceção IndexError é lançada. Caso um valor para o acumulador seja fornecido, este será o resultado da HoF REDUCE.

Exemplo 1 Reduce:


#Importando a função reduce 
from 

functools

import

reduce

#Gerando uma lista com valores definidos aleatoriamente

numeros

= [

47, 11, 42, 13

] #criando a função soma def

soma

(acc,elem)

: x =

acc

+

elem

return

x

# Aplicando a função reduce na lista. # 0 é o valor de inicialização do parâmetro acumulador. valor =

reduce

(

soma

,

numeros

,

0

) #Saída print

(valor)

113

Exemplo 2 Reduce:


#Importando a função reduce 
from 

functools

import

reduce

#criando função para verificar o comprimento def

comparar_comprimento

(nome_a, nome_b)

: if

len(nome_a) > len(nome_b)

:
return

nome_a

else: return

nome_b

#nomes de pessoas nomes = [

"João", "Maria", "Pedro", "Rodrigo Duran","Maria Clara"

] resultado =

reduce

(

comparar_comprimento

,

nomes

,"") #Saída print

(resultado)

Rodrigo Duran

Exemplo 3 Reduce:


#Importando a função reduce 
from 

functools

import

reduce

def

contar_emails_dominio

(acc,emails)

: if

email.

split

(

"@"

)[

1

] ==

dominio

: return

acc

+

1

else: return

acc

dominio =

"gmail.com"

emails = [

"joaosilva@gmail.com", "mariagomes@yahoo.com", "marcos@gmail.com", "pedrodutra@hotmail.com"

] numero_emails_dominio =

reduce

(

contar_emails_dominio

,

emails

,

0

) #Saída print(

"Número de emails do dominio:"

,

dominio

) print(

numero_emails_dominio

) Número de emails do dominio gmail.com: 2

O PODER DA COMPOSIÇÃO

Encadeando Funções de Ordem-Superior e tornando seu código muito mais enxuto (e legível)!

Compondo Funções de Ordem-Superior

Uma grande vantagem oferecida por Funções de Ordem-Superior é a composição. Como MAP e FILTER retornam um iteravel, podemos imediatamente encadear uma outra função de Ordem-Superior a partir do resultado da anterior.
Dessa forma, podemos criar funções menores que gerenciam um (ou poucos) objetivos, compondo funções mais complexas utilizando várias funções menores. Esta técnica pode reduzir o número de bugs e fazer com que o código seja mais fácil de ser compreendido.
Assim, pode-se compor quantas funções achar necessário.

Exemplo 1 Composição de Funções:


produto = [

'lapis', 'borracha', 'caderno', 'lapiseira', 'caderno'

] # função que retorna se determinada string contem a substring la def

encontra

(

lista

): return

startswith

(

"la"

) # função que retorna se uma determinada string tem tamanho maior que 5 def

tamanho

(

lista

): return

len

(

lista

)

>

5

resultado =

list

(

filter

(

encontra

,

filter

(

tamanho

,

produto

))) #Saída print(

resultado

) [

'lapiseira'

]

Exemplo 2 Composição de Funções:


# temperaturas em Fahrenheit 
temp_fahrenheit = [

78, 80, 100, 98

] # função para realizar a conversão de temperatura para Celsius def

celsius

(T)

: return

round

((

float

(

5

) /

9

) * (T-

32

),

2

) # função para encontrar altas temperaturas def

temperaturas_altas

(

x

): return

x

>

30

resultado =

list

(

filter

(

temperaturas_altas

,

map

(

celsius

,

temp_fahrenheit

))) #Saída print(

resultado

) [

37.78, 36.67

]

Exemplo 3 Composição de Funções:


def 

obter_nome

(email)

: return

email.

split

(

"@"

)[

0

] def

eh_gmail

(email)

: return

email.

split

(

"@"

)[

1

] ==

"gmail.com"

emails = [

"joaosilva@gmail.com", "mariagomes@yahoo.com.br", "marcos@gmail.com","pedrodutra@hotmail.com"

] primeiro_nome_gmail =

list

(

map

(

obter_nome

,

filter

(

eh_gmail

,

emails

))) print

(primeiro_nome_gmail)

['joaosilva','marcos']

Exemplo 4 Composição de Funções:


def 

eh_hotmail

(email)

: return

email.

split

(

"@"

)[

1

] ==

"hotmail.com"

def

converter_para_outlook

(email)

: return

email.

replace

(

"hotmail", "outlook"

) emails = [

"joaosilva@gmail.com", "mariagomes@yahoo.com.br", "marcos@gmail.com","pedrodutra@hotmail.com"

] emails_alterados =

list

(

map

(

converter_para_outlook

,

filter

(

eh_hotmail

,

emails

))) print

(emails_alterados)

['pedrodutra@outlook.com']
Universidade Estadual de Feira de Santana | UEFS - 2024 © Todos os direitos reservados