Pular para o conteúdo

Fundamentos

Listas em Python: criar, acessar, alterar e percorrer

Aprenda listas em Python: criar, acessar por índice e fatia, alterar com append e pop, entender cópias e percorrer com for, enumerate e while.

Por Prof. Rodrigo Faustino · Atualizado em · 17 min de leitura

Uma lista em Python é uma coleção ordenada de valores guardados sob um único nome. Ela é escrita entre colchetes, com os itens separados por vírgula, cada item tem uma posição numerada a partir de 0, e o programa pode consultar, trocar, acrescentar e remover itens sem criar uma variável nova para cada um. Esse é o primeiro dos tipos de dados que guardam vários valores, e quase todo programa que passa de algumas linhas acaba usando um.

Este artigo abre o módulo de estruturas de dados. Aqui veremos como criar uma lista, como ler uma posição ou um pedaço dela, como alterá-la, por que b = a não faz uma cópia, as maneiras de percorrer os itens e os erros que aparecem em quase toda turma. No fim há dois usos na ESP32: uma janela de leituras de um sensor e um conjunto de LEDs guardados numa lista.

Por que uma lista

Imagine um programa que lê as notas de cinco alunos e calcula a média. Sem listas, o caminho é criar nota1, nota2, nota3, nota4 e nota5, e repetir cada conta cinco vezes. Para vinte alunos, são vinte variáveis. Para um número que só se sabe na hora da execução, não há como escrever o programa.

Com uma lista, o programa tem um nome só, notas, e o for que você já conhece passa por cada item. O tamanho da lista pode mudar durante a execução, e o código que soma, procura ou conta continua o mesmo.

O mesmo vale para um sensor. Uma leitura isolada oscila, e para saber se a temperatura está subindo é preciso comparar várias leituras. Guardar as últimas dez numa lista é o caminho natural, e é o que o exemplo da ESP32 mais abaixo faz.

FastMindAssistente de IA local

A IA que lembra da sua vida e mora no seu computador

  • Memória de longo prazo com a fonte de cada resposta
  • Funciona offline: seus dados ficam no seu PC
  • Lê PDFs, slides, fotos e gravações de reunião
Baixar grátis para Windows

Plano Essencial grátis para sempre

Criar uma lista

A forma mais comum é escrever os itens entre colchetes. Uma lista pode ser vazia, pode ter números e pode misturar tipos:

vazia = []
notas = [8, 6, 7]
aluno = ["Ana", 20, 1.75, True]
print(vazia, notas, aluno)
print(list(range(5)))
print(list(range(2, 10, 3)))
print(list("abc"))
print([0] * 5)
print([1, 2] * 3)
print(len(vazia), len(notas), len(aluno))
print(type(notas))
print("fim")

A saída tem [] [8, 6, 7] ['Ana', 20, 1.75, True] na primeira linha, depois [0, 1, 2, 3, 4], [2, 5, 8], ['a', 'b', 'c'], [0, 0, 0, 0, 0] e [1, 2, 1, 2, 1, 2]. A linha seguinte traz 0 3 4, os tamanhos, e depois vem <class 'list'> e fim.

Quatro coisas aparecem aí. O [] cria a lista vazia, que é o ponto de partida de quase todo programa que vai montar uma lista aos poucos. O list(range(...)) transforma uma sequência do range, que você viu nos laços, numa lista de verdade. O list("abc") separa um texto em letras. E o * repete o conteúdo, o que dá uma lista de zeros pronta com [0] * 5. A função len devolve quantos itens a lista tem.

A mistura de tipos, como no caso de aluno, é permitida, mas na prática uma lista guarda itens do mesmo tipo e do mesmo significado: todas as notas, todas as leituras, todos os nomes. Quando os itens têm papéis diferentes, como nome, idade e altura, o que se quer é outra estrutura, e os próximos artigos mostram quais.

Acessar um item: o índice

A lista valores com os números 12, 45, 7, 89 e 23. Acima de cada caixa estão os índices de 0 a 4 e abaixo estão os índices negativos de menos 5 a menos 1. As caixas 45, 7 e 89 estão destacadas por uma chave com o texto valores de 1 até 4, que resulta em 45, 7, 89. Outras fatias aparecem em linha: até 2, a partir de 3 e invertida.
Cada posição tem dois índices: um contado do início, a partir de 0, e outro contado do fim.

Cada item tem uma posição, chamada índice, e ela começa em 0. O primeiro item está no índice 0, o segundo no 1, e assim por diante. Isso confunde quem está começando, porque na vida o primeiro é o número 1, mas é a regra da linguagem inteira e não tem exceção.

Os índices negativos contam do fim: -1 é o último item, -2 é o penúltimo. É a forma curta de pedir o último sem precisar calcular o tamanho.

valores = [12, 45, 7, 89, 23]
print(valores[0], valores[1], valores[4])
print(valores[-1], valores[-2], valores[-5])
print(valores[len(valores) - 1])
print(valores[1:4])
print(valores[:2])
print(valores[3:])
print(valores[::2])
print(valores[::-1])
print(valores[2:100])
print(valores[3:1])
print(valores)
print("fim")

A saída é 12 45 23, 23 89 12 e 23, que mostram os índices positivos, os negativos e o cálculo manual do último. As linhas de fatia dão [45, 7, 89], [12, 45], [89, 23], [12, 7, 23], [23, 89, 7, 45, 12], [7, 89, 23] e [], e no fim a lista original aparece intacta, seguida de fim.

Fatias: um pedaço da lista

A fatia usa dois pontos dentro dos colchetes, lista[inicio:fim], e entrega uma lista nova com os itens do inicio até o fim, sem incluir o fim. Por isso valores[1:4] traz os índices 1, 2 e 3, e não o 4. Quem já usou o range(1, 4) reconhece a regra, que é a mesma.

Quando o início é omitido, a fatia começa do começo, e quando o fim é omitido, vai até o final. O terceiro número, opcional, é o passo: [::2] pega de dois em dois e [::-1] anda de trás para frente, o que dá a lista invertida.

Duas características das fatias poupam erros. Elas não reclamam de limites exagerados: valores[2:100] simplesmente vai até o fim, e valores[3:1], que pede uma faixa impossível, devolve uma lista vazia. E elas nunca alteram a original. É diferente do que acontece com um índice só, que fora da lista dá erro, como vemos adiante.

FastTeacherPara professores

Da ementa ao semestre planejado

  • Plano de ensino e calendário montados sozinhos
  • Diário de aulas pronto para colar no SIGA
  • Slides e listas de exercícios com gabarito
Conhecer o FastTeacher

Versão Community grátis · Windows

Perguntar sobre a lista

Algumas perguntas sobre uma lista são tão comuns que existem prontas:

dados = [12, 45, 7, 89]
print(45 in dados, 50 in dados, 50 not in dados)
print(dados.index(7))
print(dados.count(45))
print(len(dados), min(dados), max(dados), sum(dados))

O in diz se o valor está na lista, e o not in diz o contrário. O index devolve a posição da primeira ocorrência, o count conta quantas vezes o valor aparece, e len, min, max e sum dão o tamanho, o menor, o maior e a soma. A saída é True False True, depois 2, depois 1 e, por fim, 4 7 89 153.

As funções min, max e sum são atalhos. Os desafios da plataforma pedem as versões feitas à mão, com laço, para que o raciocínio fique treinado, e isso será retomado no próximo artigo.

Alterar itens

Uma lista pode mudar depois de criada. Quem chega do texto, que não aceita troca de uma letra, costuma achar isso estranho, mas é o ponto central da estrutura. Atribuir a um índice troca o item daquela posição:

lista = [10, 20, 30]
lista[1] = 25
print(lista)
lista[-1] = 99
print(lista)
lista[0] = lista[0] + 1
print(lista)
lista[0:2] = [1, 2, 3]
print(lista)

A saída é [10, 25, 30], [10, 25, 99], [11, 25, 99] e [1, 2, 3, 99]. A terceira linha mostra o padrão de ler o valor, mexer nele e guardar de volta, que é o mesmo do acumulador. A última atribui uma lista a uma fatia: os dois itens das posições 0 e 1 foram trocados por três, e a lista cresceu.

Para acrescentar ou retirar itens, a lista tem métodos. Cada um faz uma coisa só, e a imagem a seguir reúne os sete mais usados, todos partindo da mesma lista [10, 20, 30]:

Tabela com sete comandos que alteram a lista 10, 20, 30. Para cada um aparecem a lista depois do comando e o valor devolvido. O append de 40 e o insert de 1 e 15 devolvem None, o pop devolve 30, o pop de 0 devolve 10, o remove de 20 devolve None, o extend com 40 e 50 devolve None e o del não devolve nada. Uma faixa diz que só o pop devolve algo útil.
Cada comando parte da mesma lista [10, 20, 30]. Só o pop devolve um valor útil.

No programa, porém, os comandos acontecem em sequência, e cada um parte do resultado do anterior:

lista = [10, 20, 30]
lista.append(40)
print(lista)
lista.insert(1, 15)
print(lista)
ultimo = lista.pop()
print(ultimo, lista)
primeiro = lista.pop(0)
print(primeiro, lista)
lista.remove(20)
print(lista)
lista.extend([40, 50])
print(lista)
del lista[1]
print(lista)
lista.clear()
print(lista)

A saída é [10, 20, 30, 40], [10, 15, 20, 30, 40], 40 [10, 15, 20, 30], 10 [15, 20, 30], [15, 30], [15, 30, 40, 50], [15, 40, 50] e [].

O append coloca um item no fim e é o método mais usado da lista. O insert(posição, valor) coloca num lugar específico e empurra o resto para a frente. O pop() tira o último item e o devolve, e o pop(0) tira o primeiro. O remove(valor) procura o valor e apaga a primeira ocorrência, e o del lista[i] apaga a posição i. O extend acrescenta vários itens de uma vez, e o clear esvazia a lista.

Há uma diferença entre esses comandos que importa mais do que parece: o pop devolve o item retirado, e todos os outros devolvem None. O motivo é que eles já alteraram a lista e não têm nada a entregar. A consequência aparece na seção de erros.

append, extend e +: a diferença que engana

Três maneiras de juntar coisas à lista dão resultados diferentes, e na pressa se confundem:

a = [1, 2]
a.append([3, 4])
print(a, len(a))
b = [1, 2]
b.extend([3, 4])
print(b, len(b))
print([1, 2] + [3, 4])
d = [1, 2, 3, 2, 2]
d.remove(2)
print(d, d.index(2))

A saída é [1, 2, [3, 4]] 3, [1, 2, 3, 4] 4, [1, 2, 3, 4] e [1, 3, 2, 2] 2. O append coloca o que receber como um item só, e por isso a lista [3, 4] entrou inteira e a lista ficou com três itens, um deles sendo outra lista. O extend abre o que recebeu e põe os elementos um a um. O + junta duas listas numa terceira, sem alterar as originais, e por isso é usado numa expressão, não como comando solto.

A última parte do exemplo mostra que o remove(2) apagou só o primeiro 2. Os outros dois continuaram na lista, e o index(2) agora encontra um deles na posição 2. Para apagar todas as ocorrências é preciso um laço ou a compreensão de lista, que o próximo artigo apresenta.

Uma lista, dois nomes

Dois quadros lado a lado. No da esquerda, b igual a a: os nomes a e b apontam para a mesma lista 1, 2, 3, e depois de b.append de 4 o print de a mostra 1, 2, 3, 4. No da direita, b igual a a.copy: a aponta para a lista 1, 2, 3 e b aponta para outra lista, que recebe o 5, e o print de a continua 1, 2, 3. Uma faixa diz que atribuir não copia a lista.
Com b = a existe uma lista e dois nomes. Com copy() existem duas listas.

Este é o ponto que mais surpreende quem vem de variáveis com números e textos. Com um número, b = a copia o valor, e mexer em b não muda a. Com uma lista não é assim. O b = a não cria uma lista nova: faz o nome b apontar para a mesma lista que a. Os dois nomes são duas etiquetas na mesma caixa.

a = [1, 2, 3]
b = a
b.append(4)
print(a, b, a is b)
c = a.copy()
c.append(5)
print(a, c, a is c)
d = a[:]
e = list(a)
print(d is a, e is a, d == a)

A saída é [1, 2, 3, 4] [1, 2, 3, 4] True, depois [1, 2, 3, 4] [1, 2, 3, 4, 5] False e, por fim, False False True. O operador is pergunta se os dois nomes apontam para o mesmo objeto, e o == pergunta se o conteúdo é igual. Depois de b = a, o is dá True: só existe uma lista. Depois de copy(), dá False: existem duas, e mexer numa não toca na outra. As formas a[:] e list(a) também fazem cópia, e ficam à escolha de quem escreve. A pergunta sobre o conteúdo, d == a, continua verdadeira, porque a cópia tem os mesmos valores.

Essa característica tem o nome de mutabilidade: a lista pode ser alterada no lugar, e por isso quem tem o nome dela enxerga a alteração. Números, textos e tuplas são imutáveis, e por isso não têm essa pegadinha.

O que isso muda nas funções

O mesmo princípio vale quando a lista é passada a uma função, como visto no artigo sobre parâmetros e argumentos. O parâmetro é um novo nome para a lista do chamador, e não uma cópia:

def adicionar(lista, x):
    lista.append(x)

def reatribuir(lista):
    lista = [0]

dados = [1, 2]
adicionar(dados, 3)
print(dados)
reatribuir(dados)
print(dados)

As duas linhas da saída são [1, 2, 3]. Na primeira, o append alterou a lista que o chamador também enxerga, e por isso a mudança sobreviveu à função. Na segunda, lista = [0] apenas fez o nome local apontar para outra lista, e a de fora ficou como estava. É a mesma lógica dos nomes locais do artigo sobre escopo de variáveis: mexer no conteúdo é uma coisa, trocar o que o nome aponta é outra.

Percorrer uma lista

Percorrer é passar por todos os itens, e a linguagem oferece mais de um jeito. Cada um serve a uma necessidade.

notas = [8, 6, 7]
for n in notas:
    print(n)
for i in range(len(notas)):
    print(i, notas[i])
for i, n in enumerate(notas):
    print(i, n)
for i, n in enumerate(notas, 1):
    print("aluno", i, n)

O primeiro laço, for n in notas, entrega cada item, e é o que se usa quando a posição não importa. O segundo percorre os índices com range(len(notas)) e lê o item por notas[i], que serve quando a posição é necessária, mas dá mais trabalho. O enumerate entrega a posição e o item juntos, e é a forma mais limpa de ter os dois. O segundo argumento, enumerate(notas, 1), muda onde a contagem começa, o que ajuda quando a posição será mostrada a uma pessoa que conta a partir de 1.

Três variantes completam o conjunto:

notas = [8, 6, 7]
i = 0
while i < len(notas):
    print(notas[i], end=" ")
    i += 1
print()
for n in reversed(notas):
    print(n, end=" ")
print()
for num, letra in zip([1, 2, 3], ["a", "b", "c"]):
    print(num, letra)

A primeira linha da saída é 8 6 7, escrita pelo while com índice, que só vale a pena quando o passo não é de um em um ou quando a lista muda durante o laço. A segunda é 7 6 8, pelo reversed, que anda de trás para frente sem criar uma lista nova. Depois vêm 1 a, 2 b e 3 c, onde o zip percorre duas listas ao mesmo tempo, emparelhando os itens de mesma posição.

Não remova itens enquanto percorre

Este é o erro que não dá mensagem nenhuma. Quem percorre uma lista e apaga itens dela ao mesmo tempo acaba com um resultado errado, sem aviso:

nums = [2, 4, 6, 8]
for n in nums:
    nums.remove(n)
print(nums)

nums = [2, 4, 6, 8]
for n in nums[:]:
    nums.remove(n)
print(nums)

A saída é [4, 8] e depois []. Na primeira versão a intenção era esvaziar a lista, e sobraram dois itens. O laço anda por posição: apaga o 2, os itens deslizam para a esquerda, e o próximo passo olha a posição 1, que agora guarda o 6, e o 4 foi pulado. A segunda versão percorre uma cópia, nums[:], e apaga na original, e por isso dá o resultado esperado. O caminho mais claro quase sempre é montar uma lista nova só com o que deve ficar. Por exemplo, [n for n in [2, 4, 6, 8, 9] if n % 2 != 0] dá [9]. Essa forma, a compreensão de lista, é o assunto do próximo artigo.

Acumuladores sobre uma lista

Os padrões dos laços, como somar, achar o maior e contar, aparecem com listas o tempo todo. A estrutura é a mesma: uma variável antes do laço, que é atualizada a cada item.

valores = [12, 45, 7, 89, 23]
soma = 0
maior = valores[0]
pares = 0
for v in valores:
    soma += v
    if v > maior:
        maior = v
    if v % 2 == 0:
        pares += 1
print("soma", soma)
print("maior", maior)
print("pares", pares)
print("media", soma / len(valores))

A saída é soma 176, maior 89, pares 1 e media 35.2. O maior começa com o primeiro item da lista, e não com 0, porque se todos os valores fossem negativos o 0 ganharia sem estar na lista. O padrão de partir do primeiro item só vale com a lista não vazia, e uma lista vazia daria erro de índice logo na primeira linha. Um programa que recebe listas de fora precisa conferir o len antes.

Listas na ESP32

Na ESP32, a lista guarda leituras e guarda objetos. O primeiro caso é a janela móvel, que mantém só as últimas leituras de um sensor para tirar uma média e suavizar a oscilação:

leituras = (510, 520, 505, 540, 530)
janela = []
for x in leituras:
    janela.append(x)
    if len(janela) > 3:
        janela.pop(0)
    print(janela, sum(janela) // len(janela))

A saída é [510] 510, [510, 520] 515, [510, 520, 505] 511, [520, 505, 540] 521 e [505, 540, 530] 525. A cada leitura nova, o append entra no fim, e quando a janela passa de três itens o pop(0) tira a mais antiga. A conta usa // para a média inteira. Numa placa de verdade, leituras viria do adc.read() dentro de um laço com sleep; o artigo sobre ADC na ESP32 mostra a leitura, e o tamanho da janela é uma escolha entre resposta rápida e leitura estável.

O segundo caso é guardar os próprios pinos. Em vez de três variáveis led1, led2 e led3, uma lista:

from machine import Pin
from time import sleep

leds = [Pin(18, Pin.OUT), Pin(19, Pin.OUT), Pin(21, Pin.OUT)]
for led in leds:
    led.on()
    sleep(0.1)
    led.off()
print("leds:", len(leds))
print("fim")

A saída é leds: 3 e fim, e o laço liga e desliga cada LED na ordem da lista. Para acrescentar um quarto LED, basta pôr outro Pin na lista, e o laço não muda. Se o programa precisar do número da posição, o laço pode usar range(len(leds)) e escrever leds[i], como no desafio Semáforo, que pede três LEDs e em que a ordem da sequência é o próprio problema.

Uma ressalva sobre memória: a ESP32 tem pouca RAM, e uma lista que cresce sem limite, por exemplo guardando uma leitura por segundo o dia inteiro, acaba esgotando a memória. A janela móvel do exemplo anterior evita isso por construção, porque a lista nunca passa de três itens.

Erros comuns

Seis mensagens cobrem quase tudo o que dá errado com listas. Os textos abaixo são os do simulador, que imita o MicroPython:

lista = [10, 20, 30]
print(lista[3])
IndexError: list index out of range

O índice 3 não existe numa lista de três itens, porque os índices vão de 0 a 2. É o erro mais frequente, e a causa quase sempre é o lista[len(lista)], que tenta ler uma posição depois da última.

lista = []
lista.pop()
IndexError: pop from empty list

O pop precisa de pelo menos um item. Quando a lista pode estar vazia, o if lista: antes do pop evita o erro.

lista = [1, 2, 3]
lista.remove(9)
ValueError: object not in sequence

O remove e o index dão ValueError quando o valor não está na lista. A mensagem do Python de computador é outra, mas o tipo do erro é o mesmo. A defesa é perguntar antes com if 9 in lista:.

lista = [1, 2, 3]
print(lista[1.5])
TypeError: list indices must be integers, not float

O índice precisa ser um inteiro, e um float é recusado. Aparece quando o índice vem de uma divisão com /, que sempre devolve float, e a correção é usar //. Com um texto no lugar, a mensagem é a mesma, com str no fim.

lista = [1, 2, 3]
print(lista("0"))
TypeError: 'list' object isn't callable

Parênteses chamam funções e colchetes acessam posições. Escrever lista(0) tenta chamar a lista como se fosse uma função.

lista = [1, 2, 3]
lista = lista.append(4)
print(lista)
lista.append(5)
None
AttributeError: 'NoneType' object has no attribute 'append'

É o efeito do que a seção de métodos anunciou: o append devolve None, e a atribuição lista = lista.append(4) troca a lista por None. O print mostra None, e o próximo append falha, porque None não tem esse método. O append altera a lista no lugar e não precisa de atribuição.

O que costuma aparecer em sala

Os padrões abaixo se repetem em quase toda turma que chega a listas, de iniciantes a gente com anos de programação.

O primeiro é o índice. Quem conta de 1 acaba lendo uma posição a mais, e o lista[len(lista)] dá IndexError toda vez. A cura é decorar uma frase: numa lista de n itens, os índices vão de 0 a n - 1, e o último também pode ser lido com -1.

O segundo é o lista = lista.append(x), visto acima. Quase todo mundo que escreve isso já fez a mesma atribuição com textos e números, em que ela é necessária, e leva a mesma ideia para um método que altera no lugar.

O terceiro é o b = a achando que é cópia. O sintoma é uma lista que muda "sozinha" em outro ponto do programa, e a investigação costuma terminar numa atribuição esquecida a quinze linhas dali. Uma dica útil de depuração é imprimir a is b.

O quarto é apagar itens dentro do for, que não dá erro e entrega resultado errado, o que torna o problema mais difícil de achar do que um erro com mensagem.

O quinto é confundir append com extend, e a lista com uma lista dentro, que só aparece quando o programa tenta somar ou imprimir os itens. O sexto é esperar que o remove apague todas as ocorrências. E o sétimo, conhecido de quem leu o artigo sobre parâmetros, é usar [] como valor padrão de um parâmetro, o que faz a lista ser compartilhada entre todas as chamadas da função.

Exercício: relatório de notas

Escreva um programa que pergunte quantas notas serão lidas, leia cada uma, guarde numa lista e mostre a lista, a média, a maior nota e as notas acima da média.

quantidade = int(input("quantas notas: "))
notas = []
for i in range(quantidade):
    n = int(input("nota: "))
    notas.append(n)
media = sum(notas) / len(notas)
print("notas", notas)
print("media", media)
print("maior", max(notas))
acima = []
for n in notas:
    if n > media:
        acima.append(n)
print("acima da media", acima)

Com as entradas 3, 8, 6 e 7, as quatro linhas finais são notas [8, 6, 7], media 7.0, maior 8 e acima da media [8]. A lista nasce vazia e cresce com o append, a média usa sum e len, e a lista acima é montada com o mesmo padrão. Para treinar, troque o max por um laço com maior e faça o programa mostrar também as notas abaixo da média. O que acontece se o usuário digitar 0 na primeira pergunta? Teste e proteja o programa.

Perguntas frequentes

Qual é a diferença entre lista e tupla? A lista pode ser alterada depois de criada e a tupla não. A tupla já apareceu ao devolver vários valores de uma função, e o artigo 24 explica quando preferi-la.

Por que os desafios falam em "vetor"? É o nome que se usa em lógica de programação para uma sequência de itens do mesmo tipo. Em Python, o vetor é uma lista. Os desafios l49 a l54 têm essa palavra no nome, mas o código que se escreve neles é uma lista comum.

Uma lista pode ter itens de tipos diferentes? Pode, mas só vale a pena quando os itens significam coisas diferentes e a posição de cada um é fixa. Para listas de coisas do mesmo tipo, a mistura costuma ser sinal de erro.

Posso ter uma lista dentro de outra? Pode, e é assim que se representa uma tabela, com linhas e colunas. Isso é assunto do artigo 28, sobre matrizes.

Qual a diferença entre pop, remove e del? O pop age pela posição e devolve o item. O remove age pelo valor. O del age pela posição e não devolve nada.

Para continuar

Os desafios l49-vetor-primeiro, l50-vetor-len, l51-vetor-soma, l52-vetor-busca, l53-vetor-inversao e l54-vetor-medio praticam exatamente o que foi visto aqui, do acesso por índice à média de uma lista.

Para rever as bases desta leitura, os artigos sobre funções com def, return e lambda, map, filter e sorted mostram como as funções recebem e devolvem listas.

O próximo artigo trata das operações com listas: busca, filtragem e compreensões de lista. Ele mostra como achar um valor sem index, como montar uma lista nova só com o que interessa e como escrever em uma linha o que aqui levou quatro.

Para praticar no PyPlaca

Trilhas

Lições

Fichas de componentes

FastTeacherPara professores

Da ementa ao semestre planejado

  • Plano de ensino e calendário montados sozinhos
  • Diário de aulas pronto para colar no SIGA
  • Slides e listas de exercícios com gabarito
Conhecer o FastTeacher

Versão Community grátis · Windows

FastMindAssistente de IA local

A IA que lembra da sua vida e mora no seu computador

  • Memória de longo prazo com a fonte de cada resposta
  • Funciona offline: seus dados ficam no seu PC
  • Lê PDFs, slides, fotos e gravações de reunião
Baixar grátis para Windows

Plano Essencial grátis para sempre

FastTeacherPara professores

Da ementa ao semestre planejado

  • Plano de ensino e calendário montados sozinhos
  • Diário de aulas pronto para colar no SIGA
  • Slides e listas de exercícios com gabarito
Conhecer o FastTeacher

Versão Community grátis · Windows