10 minutos de leitura

3 erros comuns de iniciantes em Python

Por Juliano Faccioni
Conteúdos do artigo

Descubra erros frequentemente cometidos por iniciantes em Python e aprenda como evitá-los.

Neste artigo, você vai conhecer alguns erros comuns em scripts escritos em Python. Alguns deles podem ser encontrados até mesmo em códigos desenvolvidos por programadores mais experientes, portanto preste atenção!

Abordaremos alguns conceitos um pouco avançados, mas ainda dentro do que você aprende em nosso curso Python Starter, para iniciantes em programação. A versão completa deste conteúdo você encontra no artigo Os principais erros de iniciantes em Python.

Erro #1: 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
Testar

Como 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]
Testar

Note 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 #2: 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(). Ela 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'>
Testar

Como 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!
valor = 'Olá Mundo!'

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:

valor = 'Olá Mundo!'

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
Testar

Alé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
Testar

Essa função é tão útil que está na nossa lista de 15 hacks básicos de Python para iniciantes.

Erro #3: 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)
Testar

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:

Resultado da execução do script analise.py
Resultado da execução do script analise.py

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)

analise.py

from valores import pegar_x

x = pegar_x()
y = x / 2
print("O resultado da análise é", y)

Executando analise.py novamente no terminal, temos:

Resultado da execução do script analise.py após modificações
Resultado da execução do script analise.py após modificações.

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 seja executado 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 com a Asimov Academy

Neste artigo, vimos alguns erros comuns de iniciantes em Python que são encontrados com frequência alta nos códigos de quem começa a aprender Python.

Se você estiver com ainda mais vontade de se aprofundar no estudo dessa linguagem de programação, 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 e web scraping.

Continue aprendendo e até a próxima!

Inscreva-se gratuitamente e fique atualizado

Receba toda semana um resumo dos principais conteúdos da Asimov direto no seu e-mail. 100% livre de spam.

Áreas de interesse:
Conteúdos do tutorial