Descubra quais são os erros mais comuns em Python para iniciantes e aprenda a contorná-los.
Python é uma linguagem de programação muito procurada por iniciantes. Embora seja mais simples e intuitiva do que outras linguagens, ainda há “armadilhas” em seu uso, principalmente para quem está começando.
Neste artigo, exploraremos os principais erros que os iniciantes em Python cometem. Além disso, vamos entender por que cada erro ocorre e qual é a melhor forma de solucioná-los. Então, se você ainda não tem conhecimento suficiente para acompanhar este conteúdo, recomendamos o curso gratuito Python para Iniciantes, da Asimov Academy. Caso contrário, vamos em frente!
Seu primeiro projeto Python – curso grátis com certificado!
Vá do zero ao primeiro projeto em apenas 2 horas com o curso Python para Iniciantes.
Comece agoraErro #1: Confundir strings e variáveis
Um erro extremamente comum para quem está começando em Python é confundir o que é uma string e o que é uma variável. Ambos aparecem no script como texto, mas são conceitualmente diferentes.
Uma string é um tipo de dado em Python, uma sequência de caracteres que representa algum tipo de informação textual. 'Olá Mundo!'
, "Juliano"
, 'RJ95-K'
e "Análise de Dados com Python"
são exemplos de strings.
Já uma variável é simplesmente um nome atribuído a algum dado. Em programação, usamos variáveis porque é mais fácil usar nomes para identificar valores em vez de usarmos os valores diretamente.
Observe a comparação abaixo, na qual calculamos a área de um círculo com raio 5:
# sem variaveis
area_circulo = 3.1415 * (5 ** 2)
# com variaveis
raio = 5
pi = 3.1415
area_circulo = pi * (raio ** 2)
TestarPerceba como, no segundo exemplo, é mais fácil entender o que o código está fazendo, pois utilizamos nomes (variáveis) para os valores do raio e de pi.
Obviamente, também é possível atribuir uma variável a uma string. O código abaixo exibe o valor "Juliano"
, que está guardado dentro da variável nome
:
nome = "Juliano"
print(nome)
TestarPara diferenciar uma string de uma variável, baseie-se nos seguintes pontos:
- Strings são valores, e o valor de uma string é uma sequência de caracteres.
- Variáveis são nomes que podem ser atribuídos a um valor qualquer (inclusive a uma string).
- Strings são sempre escritas com aspas duplas ou simples. Portanto, não use aspas para acessar uma variável.
- Numa atribuição de valor com o operador
=
, variáveis ficam sempre à esquerda, enquanto strings ficam à direita.
Lembre-se dessa explicação na próxima vez em que tentar acessar o valor da variável nome
usando a string "nome"
!
Erro #2: Sobrescrever nomes de funções e objetos
Em Python, existem diversas funções embutidas (built-in functions) que estão disponíveis para uso a qualquer momento. Alguns exemplos são as funções print()
, input()
, list()
e id()
. A documentação do Python apresenta a lista completa (em inglês).
O erro ocorre quando sobrescrevemos uma dessas funções com uma variável nossa. No exemplo abaixo, criamos uma variável chamada list
, que guarda uma lista de valores qualquer. O problema é que esse nome de variável sobrescreve a função embutida list()
:
list() # não dá erro
list = [1, 2, 4, 7, 3]
list() # TypeError: 'list' object is not callable
TestarInicialmente, nenhum erro é gerado ao chamarmos list()
(esta chamada apenas cria uma lista vazia, descartada em seguida). Contudo, após sobrescrevermos a função e executarmos list()
novamente, um erro é gerado. Efetivamente, perdemos a referência à função original!
Para evitar a sobrescrita de uma função embutida, a dica é usar um editor de texto com destaque para a sintaxe de Python, como o VS Code. Nesse caso, ao digitar a palavra list
, a cor do texto muda, indicando que é um nome “reservado” pelo Python.
Erro #3: Não entender a diferença entre print
e return
Este erro em Python é extremamente comum entre iniciantes na linguagem. Muitas vezes, eles não entendem qual é a utilidade de “dar print” em algumas linhas ou o que significa de fato retornar um valor.
Em poucas palavras, “printar” significa exibir um valor na tela, enquanto “retornar” refere-se a receber um valor que se pode acessar mais tarde, em outras partes do código.
Vamos usar um exemplo para entender melhor.
Imagine que a função conta_complexa()
é uma operação bastante demorada. Se quisermos apenas exibir o resultado dessa operação, podemos usar a função print()
:
print(conta_complexa())
TestarNote que o código acima apenas exibe o resultado uma única vez. E se quisermos ver o resultado novamente? E se precisarmos fazer uma segunda operação com o resultado? Nesses casos, é necessário chamar a função conta_complexa()
uma nova vez, o que ocupa novamente todo o tempo de operação.
Por outro lado, se quisermos realizar operações com o resultado, precisamos armazenar o retorno da função conta_complexa()
em uma variável:
resultado = conta_complexa()
print(resultado)
resultado_dividido = resultado / 2
print(resultado_dividido)
# ...
TestarNesse exemplo, salvamos o retorno da função na variável resultado
. A partir desse momento, temos a liberdade de usar o valor da forma como quisermos: podemos realizar novas operações matemáticas ou exibi-lo quantas vezes quisermos com print()
. Tudo isso sem precisar executar a função conta_complexa()
uma segunda vez!
Notebooks do Jupyter x shell de IPython
A confusão entre print
e return
vem principalmente do uso de ferramentas como Notebooks do Jupyter ou shell de IPython. Tais ferramentas são excelentes para iniciantes testarem a funcionalidade da linguagem, mas podem confundir por apresentarem um funcionamento diferente de um script tradicional de Python.
Um shell de Python funciona em um loop REPL (do inglês read-evaluate-print loop). Isso tem uma implicação importante: todo valor retornado e que não é salvo em uma variável é printado automaticamente ao console. Essa funcionalidade é bastante prática, mas também é a fonte principal da confusão.
Veja o exemplo abaixo, executado em um shell de IPython:
- Em 1) e 2), atribuímos valores às variáveis
x
ey
. Nada aparece na linha de output, pois todo retorno foi devidamente “capturado” por uma variável. - Em 3), realizamos a operação
x + y
. O valor resultante foi retornado, mas não foi “capturado” por nenhuma variável. Logo, o IPython decide exibir o valor retornado na linha de output.- O prefixo
Out[3]
, em vermelho, indica que algum valor foi retornado pela expressão inserida na linha de input diretamente acima(In[3]
).
- O prefixo
- Em 4), realizamos a mesma operação, porém a entregamos para a função
print
. Como explicado anteriormente, a funçãoprint
exibe o valor entregue a ela, porém não o retorna. (Na realidade, a funçãoprint
retorna sempre o valorNone
, que representa a ausência de retorno.)- Podemos confirmar isso se escrevermos
resultado = print(x + y)
. Nesse caso, a variávelresultado
terá o valorNone
. - O valor 5, resultante da operação
x + y
, foi apenas exibido, mas não foi retornado. Isso é indicado pela falta de prefixoOut
na linha em que o 5 está exibido.
- Podemos confirmar isso se escrevermos
A imagem abaixo mostra a mesma situação dentro de um Notebook do Jupyter. Veja que, apesar da aparência diferente do Notebook, a mesma situação acontece:
Erro #4: Modificar uma lista enquanto itera sobre ela
Este é um erro clássico em programação e acontece quando você tenta modificar uma lista (ou qualquer outra sequência) enquanto está iterando sobre ela.
Para exemplificar, digamos que você deseja filtrar números maiores que 100 de uma lista de valores qualquer. Inicialmente, você pode pensar em fazer algo como o código abaixo:
valores = [300, 10, 90, 150, 120, 40]
for i in range(len(valores)):
valor = valores[i]
if valor > 100:
del valores[i]
print(valores)
# ERRO: IndexError: list index out of range
TestarComo podemos ver, o código não funcionou, gerando um IndexError
durante sua execução. Mas o que aconteceu exatamente?
Na linha del valores[i]
dentro do loop, elementos da lista valores
são deletados. Com isso, o tamanho da lista diminui ao longo das iterações.
Contudo, como iniciamos a iteração escrevendo for i in range(len(valores))
, a variável i
continua a iterar até o tamanho original da lista, antes de ter seus elementos deletados. Isso significa que, eventualmente, a linha valor = valores[i]
acessa valores além do número de elementos da lista, produzindo o IndexError
.
Lembre-se: nunca modifique um objeto enquanto você itera sobre ele!
A forma correta de filtrar elementos de uma lista é inicializar uma nova lista vazia e adicionar elementos a ela, conforme a lógica de filtro. No nosso exemplo com a lista valores
, o filtro pode ser feito da seguinte forma:
valores = [300, 10, 90, 150, 120, 40]
valores_filtrados = []
for i in range(len(valores)):
valor = valores[i]
if valor <= 100:
valores_filtrados.append(valor)
print(valores_filtrados)
# output: [10, 90, 40]
TestarNote que a comparação na linha if valor <= 100:
agora é o inverso da anterior; nesse caso, queremos adicionar valores à lista de valores filtrados somente se eles forem iguais ou menores a 100.
Erro #5: Usar a função type para identificar o tipo de um dado
Ao aprendermos sobre tipos de dados, é muito comum nos depararmos com a função type()
, a qual retorna o tipo de dado do argumento que recebe. Por exemplo:
print(type('string_qualquer'))
# output: <class 'str'>
print(type(100))
# output: <class int'>
print(type(False))
# output: <class 'bool'>
TestarComo podemos perceber, o valor exibido embaixo é sempre o tipo de dado correspondente ao argumento passado para a função type()
.
O problema ocorre quando type()
é usado para checar o tipo de dado de uma certa variável e, a partir disso, definir a lógica do seu programa. Algo como:
# Não faça isso!
if type(valor) == str:
# lidar com string
elif type(valor) == float:
# lidar com float
# etc...
Mas, afinal, qual é o problema com o código acima?
Embora ele funcione para casos simples, a função type()
possui algumas limitações. No lugar dela, prefira sempre usar a função isinstance()
para checar o tipo de um dado.
if isinstance(valor, str):
# lidar com string
elif isinstance(valor, float):
# lidar com float
# etc...
Por exemplo, a função type()
não consegue lidar de forma apropriada com herança de classes (caso você não saiba o que é uma classe, temos um artigo sobre os conceitos de programação orientada a objetos).
Se criarmos nossa própria subclasse de str
, por exemplo, apenas a função isinstance()
a considera como sendo uma instância de str
de fato:
class MinhaString(str):
pass
s = MinhaString('abc')
print(type(s) == str)
# output: False
print(isinstance(s, str))
# output: True
TestarAlém disso, a função isinstance()
permite checar múltiplos tipos de dados ao mesmo tempo. Se quisermos conferir se um certo dado é um int
ou float
, por exemplo, podemos fazer facilmente da seguinte forma:
valor = 10
if isinstance(valor, (int, float)):
print('Valor é numero')
# output: Valor é numero
TestarEssa função é tão útil que está na nossa lista de 15 hacks básicos de Python para iniciantes.
Erro #6: Não utilizar funções no seu script
Quando começamos a aprender sobre Python ou quando precisamos apenas escrever um script rápido e curto, é comum simplesmente “largarmos” as linhas de código sem prestar muita atenção em sua organização.
Contudo, quando nosso código começa a evoluir, é natural organizarmos diferentes porções lógicas em scripts separados. É possível importar a funcionalidade de um script a partir de outro usando a palavra-chave import
. Nesse momento, muitos iniciantes ficam confusos quando o código acaba sendo executado ao ser importado.
Imagine, por exemplo, que você possui dois scripts: valores.py
e analise.py
. Eles possuem o seguinte código:
valores.py
x = 10
print("O valor é", x)
analise.py
from valores import x
y = x / 2
print("O resultado da análise é", y)
O que acontece se executarmos o script analise.py
? Vejamos:
A mensagem contida no script valores.py
foi exibida, apesar de não termos importado nada relacionado a ela! Por que isso aconteceu?
Quando importamos um script, todo o código existente nele é lido e executado. É por isso que o resultado da linha print("O valor é", x)
aparece no terminal, por mais que tivéssemos interesse apenas na variável x
.
O que aconteceria se o script desorganizado contivesse funções demoradas, que realizam um cálculo pesado ou criam conexões com bancos de dados? Nesse caso, mesmo se quiséssemos apenas importar uma variável, teríamos de esperar o tempo de execução de tais processos não relacionados.
A solução é simples: precisamos reestruturar o código de valores.py
em funções, para que elas não sejam executadas diretamente ao importar o código. No lugar disso, elas serão computadas apenas quando forem explicitamente executadas.
Abaixo, apresentamos uma ideia de reestruturação simples:
valores.py
def pegar_x():
x = 10
return x
def exibir_x():
x = pegar_x()
print("O valor é", x)
Testaranalise.py
from valores import pegar_x
x = pegar_x()
y = x / 2
print("O resultado da análise é", y)
TestarExecutando analise.py
novamente no terminal, temos:
Sucesso! A mensagem “o valor é 10”, que movemos para dentro da função exibir_x()
, não apareceu no output. Faz sentido: a função não foi executada em nenhum momento.
Esse é um exemplo simples, mas que demonstra claramente a diferença de ter um script organizado em funções. Além de impedir que algum código desnecessário se execute na importação, criar funções ajuda a limpar e organizar o próprio código e também a poupar tempo do desenvolvedor.
Aprenda mais sobre Python
Neste artigo, visitamos alguns dos erros mais comuns que os iniciantes encontram em Python. Apesar de os conceitos discutidos serem simples, eles são a fonte de grandes dores de cabeça para quem é iniciante em Python. Para complementar os estudos, recomendamos a leitura do artigo abaixo:
Se você pretende se aprofundar em Python e programar como um profissional, recomendamos nossa Trilha Python Office. Nela, você aprenderá Python do zero e será capaz de montar diversas automações com e-mails, arquivos de Excel e PDFs, além de web scraping.
Python Office
Cursos de programação gratuitos com certificado
Aprenda a programar e desenvolva soluções para o seu trabalho com Python para alcançar novas oportunidades profissionais. Aqui na Asimov você encontra:
- Conteúdos gratuitos
- Projetos práticos
- Certificados
- +20 mil alunos e comunidade exclusiva
- Materiais didáticos e download de código
Comentários