sábado, 4 de maio de 2013

[Python] O perigo de importar tudo (universal imports)

Olá pessoal, nesse post iremos falar sobre a importação universal. Sabemos que basta utilizar o símbolo * (asterisco) para importar todas as funções de um módulo. Exemplo:

from math import *

Mas será que não há perigo algum de se fazer isso? Podemos fazer isso, mas a questão é: devemos realmente importar tudo?

Vamos ilustrar com uma situação de código, veja o código abaixo:


Na linha 3 eu fiz um import de todas as funções do módulo math utilizando o * (asterisco). 

Na linha 5 temos uma implementação de uma função minha chamada sqrt, perceba que essa função tem um erro proposital, ao invés dela calcular a raiz quadrada, ela na verdade está calculando o quadrado de um número como você pode perceber no retorno dessa função na linha 6.

Tudo bem, eu tenho minha função sqrt implementada, mas sabemos que o módulo math também possui uma função chamada sqrt. E agora? Qual função sqrt está sendo chamada na linha 8?

A saída do código acima é 81. Passamos o número 9 (linha 8) para a função sqrt e ela retornou 81, ou seja, retornou o quadrado do número 9. Então podemos concluir que a função sqrt utilizada para o cálculo foi a função que eu implementei na linha 5, pois é ela que retorna ERRONEAMENTE o quadrado de um número. Se tivesse sido chamada a função sqrt da math, obteríamos o resultado 3, pois 3 é a raiz quadrada de 9.

Pois bem, esse é um código simples, na mesma hora você perceberia que a função implementada na linha 5 contém um erro de lógica e que na verdade está calculando é o quadrado de um número e não a raiz quadrada. Mas já pensou um código muito grande, com vários import's e funções com o mesmo nome de várias funções não só do módulo math como de outros módulos? 

Será que importar tudo é uma boa ideia? Nessa pequena ilustração vimos que não, você não tem a segurança de que as funções estão realmente associadas ao módulo que você está importando.

Como resolver? Importar a função específica do módulo conforme for necessário. Veja o exemplo de código abaixo:


Veja que na linha 3 eu importei o módulo math. Continuo tendo a função sqrt na linha 5 que calcula de forma errada a raiz quadrada. Mas na linha 8 eu faço math.sqrt(), ou seja, tenho a certeza de que a função sqrt() chamada é a do módulo math e que, portanto, calcula de forma correta a raiz quadrada.

Você pode está se perguntando: ah, mas para quê eu iria fazer uma função para calcular a raiz quadrada se já tem no módulo math? A questão não é essa, a questão é você ter funções com o mesmo nome de funções de módulos que você importou tudo e, em alguma parte do código, você não ter a certeza de que determinada função está associada àquele módulo que foi importado.

Quaisquer dúvidas deixem nos comentários, até a próxima!


Nenhum comentário: