Estamos perto de dar início ao módulo de orientação a objetos, que é um assunto tortuoso pra muita gente no início, e nos últimos tópicos ando dando uma palhinha do que será o assunto, como no tópico anterior que criei uma classe em outro arquivo e importei para nosso programa como um pacote.
Dito isso, em Python, praticamente tudo é considerado um objeto. Números inteiros são objetos. Números de ponto flutuante são objetos. Strings, funções, sequências, etc, tudo é um objeto.
Por conta desse tipo de característica eu relembro algo que foi dito quando falei de sequências que foi o fato de listas, tuplas e dicionários aceitarem qualquer tipo de dado como dado, inclusive funções. Nos exemplos que dei sobre o assunto adicionei diversos objetos a um contêiner como uma lista e um deles sempre foi uma função:
lista = [
1, 2, 2.1, 3.4, 'Sardinhice', 'Bastter.com',
('tupla'), ['outra lista', 'dentro da minha lista'],
{'ODPV': 'ON', 'ITUB': 'PN'}, lambda x: x + 2
]
print(lista)
# >>> [1, 2, 2.1, 3.4, 'Sardinhice', 'Bastter.com', 'tupla', ['outra lista', 'dentro da minha lista'], {'ODPV': 'ON', 'ITUB': 'PN'}, <function <lambda> at 0x0019C780>]
Notem que o último elemento da minha lista é uma função lambda.
Listas bagunçadas assim não são lá uma boa prática de programação, mas é interessante notar que eu posso inserir funções dentro de contêineres.
Relembrando assuntos anteriores, ao definir uma função lambda e atribuir tal função a uma variável, eu posso chamar a função usando o nome da variável:
func_lambda = lambda x, y, z: x * y * z
resultado = func_lambda(5, 10, 15)
print(resultado)
# >>> 750
Oras, se eu atribuí uma função a uma variável, e se eu tenho uma função dentro de um contêiner, o que me impede de chamar a função dentro do contêiner? Vamos observar:
lista = [
1, 2, 2.1, 3.4, 'Sardinhice', 'Bastter.com',
('tupla'), ['outra lista', 'dentro da minha lista'],
{'ODPV': 'ON', 'ITUB': 'PN'}, lambda x: x + 2
]
# Acessando o último elemento da lista pelo índice [-1]
print(lista[-1])
# >>> <function <lambda> at 0x015CC780>
# Chamando a função passando 5 como argumento
print(lista[-1](5))
# >>> 7
Vimos que funciona. E isso define bem o fato de funções serem objetos de primeira classe. Podemos atribuir funções a variáveis, "conteinerizar" funções, ou seja, adicionar funções dentro de sequências como tuplas e listas, enfim, podemos fazer várias coisas usando essa característica de as funções serem objetos tais como outros quaisquer da linguagem.
Visto que tal comportamento é viável, vamos brincar um pouco mais com esse comportamento das funções:
# Criando uma lista de funções
lista_de_funcoes = [lambda x: x + 10, lambda x: x - 10, lambda x: x * 10, lambda x: x / 10]
# Iterando sobre a lista, chamando cada função de forma isolada passando 5 como argumento
for funcao in lista_de_funcoes:
print(funcao(5))
# >>> 15
# >>> -5
# >>> 50
# >>> 0.5
# Chamando a função da posição 2 da lista de funções passando 70 como argumento
print(lista_de_funcoes[2](70))
# >>> 700
# Criando um dicionário de funções
dic_de_funcoes = {
'soma': lambda x, y, z: x + y + z,
'subtracao': lambda x, y, z: x - y - z,
'multiplicacao': lambda x, y, z: x * y * z,
'divisao': lambda x, y, z: x / y / z
}
# Chamando a função de multiplicação do dicionário
print(dic_de_funcoes['multiplicacao'](5, 6, 7))
# >>> 210
E isso funciona não somente com funções anônimas, como também funciona com funções nomeadas:
def soma(x, y):
return x + y
def subtracao(x, y):
return x - y
def multiplicacao(x, y):
return x * y
def divisao(x, y):
return x / y
dic_de_funcoes_nomeadas = {
'soma': soma,
'subtracao': subtracao,
'multiplicacao': multiplicacao,
'divisao': divisao
}
print(dic_de_funcoes_nomeadas['soma'](50, 65))
print(dic_de_funcoes_nomeadas['subtracao'](50, 65))
print(dic_de_funcoes_nomeadas['multiplicacao'](50, 65))
print(dic_de_funcoes_nomeadas['divisao'](50, 65))
# >>> 115
# >>> -15
# >>> 3250
# >>> 0.7692307692307693
Também obtivemos o comportamento esperado.
Eu particularmente no início achava muito confuso esse tipo de comportamento de funções então tentei deixar de uma forma didática pra ver se fica tranquilo pra quem nunca programou. Qualquer dúvida podem postar aí.