# Listas, tuplos e strings

Indexação, slices, mutabilidade, aliasing, métodos e transformações de texto.

Página: https://resumos.rgo.pt/cadeiras/ct-iadp/listas-tuplos-strings/

Uma sequência guarda elementos por ordem. Um índice escolhe um elemento; um slice escolhe uma parte da sequência. Listas, tuplos e strings partilham estas operações, mas diferem no que podes alterar.

## Índices e slices

Com `valores = [10, 20, 30, 40, 50]`, os índices positivos são 0 a 4. `valores[-1]` é 50 e `valores[-5]` é 10.

`valores[inicio:fim:passo]` seleciona do início, incluído, ao fim, excluído. `valores[1:4]` dá `[20, 30, 40]`. `valores[::2]` dá `[10, 30, 50]`. `valores[::-1]` inverte a ordem. Um índice fora dos limites dá erro; um slice pode cortar nos limites e devolver uma sequência vazia.

| Operação | Resultado para `valores` |
| --- | --- |
| `len(valores)` | 5 |
| `valores[:2]` | `[10, 20]` |
| `valores[2:]` | `[30, 40, 50]` |
| `valores[-3:-1]` | `[30, 40]` |
| `30 in valores` | `True` |

## Alterar uma lista

`append(x)` acrescenta um elemento. `extend(iteravel)` acrescenta cada elemento do iterável. Com uma lista `[1]`, `append([2, 3])` cria `[1, [2, 3]]`; `extend([2, 3])` cria `[1, 2, 3]`.

`insert(i, x)` insere antes da posição `i`. `remove(x)` retira a primeira ocorrência de um valor e falha se não o encontrar. `pop(i)` retira e devolve o elemento naquela posição. Sem argumento, `pop` usa a última posição.

`lista.sort()` altera a própria lista e devolve `None`. `sorted(lista)` devolve outra lista ordenada. Não escrevas `lista = lista.sort()`, porque perderias a associação à lista.

`index(x)` devolve a posição da primeira ocorrência e falha se o valor não existir. `count(x)` conta ocorrências e pode devolver zero. `reverse()` inverte a lista atual; `clear()` remove todos os seus elementos. Estes métodos de alteração devolvem `None`, exceto operações como `pop`, que devolvem o elemento retirado.

`del lista[i]` remove por posição e `del lista[inicio:fim]` remove um slice. `del lista[:]` esvazia o objeto, conservando os nomes que o referem; `del lista` apaga a associação desse nome, não necessariamente o objeto. `list(iteravel)` constrói outra lista a partir dos seus elementos.

## Dois nomes para a mesma lista

Atribuir uma lista a outro nome não cria uma cópia:

```python
original = [2, 4, 6]
alias = original
copia = original.copy()
alias[0] = 99
copia.append(8)
print(original)
print(copia)
```

A saída é `[99, 4, 6]` e `[2, 4, 6, 8]`. `alias` e `original` apontam para a mesma lista. `copia` aponta para outra lista.

Esta cópia é **superficial**: numa lista de listas, copia a lista exterior, mas continua a partilhar as listas interiores. `[[0] * 3] * 2` repete referências à mesma linha. Para linhas independentes, usa `[[0] * 3 for _ in range(2)]`.

## Vetores e matrizes com listas

Uma lista de números pode representar um vetor. Para vetores de igual comprimento, o produto escalar soma produtos das posições correspondentes. Em `[2, 3, 4]` e `[1, 0, -2]`, calculamos `2 × 1 + 3 × 0 + 4 × (−2) = −6`.

```python
a = [2, 3, 4]
b = [1, 0, -2]
if len(a) != len(b):
    raise ValueError("Vetores com dimensões diferentes")
produto = 0
for i in range(len(a)):
    produto += a[i] * b[i]
print(produto)
```

O acumulador começa em zero. Após cada posição, vale 2, 2 e −6. `zip(a, b)` também pode emparelhar valores, mas termina quando a sequência mais curta termina; verifica os comprimentos antes de o usar para este cálculo.

Uma lista de listas representa uma matriz. `m[i][j]` acede à coluna `j` da linha `i`. `len(m)` conta linhas; `len(m[i])` conta elementos dessa linha. Uma matriz retangular tem todas as linhas do mesmo comprimento.

```python
a = [[2, 1], [0, 3]]
b = [[4, 0], [5, -1]]
if len(a) != len(b) or any(len(x) != len(y) for x, y in zip(a, b)):
    raise ValueError("Matrizes com dimensões diferentes")
soma = []
for i in range(len(a)):
    linha = []
    for j in range(len(a[i])):
        linha.append(a[i][j] + b[i][j])
    soma.append(linha)
print(soma)
```

O resultado é `[[6, 1], [5, 2]]`. O ciclo externo escolhe a linha e o interno percorre as colunas. Criamos uma lista nova em cada linha. `[[0] * 2] * 2` repetiria referências à mesma lista: alterar uma linha poderia alterar a outra. Usa `[[0] * 2 for _ in range(2)]` para criar duas linhas independentes.

Uma soma de listas, `a + b`, concatena as linhas; não soma as células. A [parte de NumPy](https://resumos.rgo.pt/cadeiras/ct-iadp/numpy/) apresenta operações vetorizadas, com arrays e eixos explícitos.

## Tuplos e desempacotamento

Um tuplo é uma sequência que não permite substituir os seus elementos. `ponto = (2, 5)` pode representar duas coordenadas. `x, y = ponto` associa a primeira a `x` e a segunda a `y`. O número de nomes deve corresponder ao número de valores, a menos que uses captura com `*`.

Um tuplo de um elemento precisa de vírgula: `(3,)`. `(3)` é apenas o inteiro 3 entre parênteses. Um tuplo pode conter uma lista; não podes substituir essa lista dentro do tuplo, mas a lista continua a ser mutável.

## Transformar texto

Uma string é imutável. `nome[0] = "A"` falha. Métodos como `strip`, `lower` e `replace` devolvem novas strings, pelo que precisas de guardar o resultado se quiseres usá-lo depois.

```python
linha = "  Porto;3;2.50  "
campos = linha.strip().split(";")
cidade = campos[0].lower()
quantidade = int(campos[1])
preco = float(campos[2])
print(cidade, quantidade * preco)
print(" | ".join(campos))
```

A primeira linha é `porto 7.5`. A segunda é `Porto | 3 | 2.50`. `strip` retira espaços nos extremos, `split` divide pelo separador e `join` junta strings com um separador entre elas. `strip("ab")` retira caracteres `a` e `b` dos extremos; não retira uma substring exata.

`find` devolve o índice da primeira ocorrência, ou -1 se não existir. `count` conta ocorrências não sobrepostas. `startswith` e `endswith` testam extremos. Ao ordenar strings, Python compara códigos dos caracteres, não regras linguísticas de ordenação.

## Construir uma nova lista

```
quadrados = [n * n for n in range(1, 4)]
positivos = [n for n in [-1, 2, 0, 3] if n > 0]
```

Uma compreensão calcula um elemento por valor percorrido. A condição opcional seleciona os valores antes de os transformar. Os resultados são `[1, 4, 9]` e `[2, 3]`. Se a expressão tiver muitos ramos, usa um ciclo normal para tornar os passos legíveis.

## Ver as operações em ação

## Exercícios

Selecionar posições

Com x = \[10, 20, 30, 40, 50, 60\], qual é a soma de x\[1:5

\]?

Primeira pista

Começa no índice 1 e avança de dois em dois sem incluir o índice 5.

Mais uma pista

Selecionas os índices 1 e 3.

Ver solução

Os valores são 20 e 40; a soma é 60.

#### Erros frequentes

Somar os valores dos índices 1, 3 e 5, incluindo o limite final.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/ct-iadp/listas-tuplos-strings/#%C3%ADndices-e-slices)

Prever uma alteração partilhada

a = \[1, 2\]; b = a; c = a.copy(); b\[0\] = 9. Quanto vale c\[0\]?

Primeira pista

Só a e b apontam para a mesma lista.

Mais uma pista

c foi criada antes da alteração e tem os seus próprios elementos exteriores.

Ver solução

c\[0\] continua a ser 1. a\[0\] e b\[0\] passam ambos a 9.

#### Erros frequentes

Tratar toda a atribuição como uma cópia ou concluir que a cópia superficial partilha estes inteiros substituídos.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/ct-iadp/listas-tuplos-strings/#dois-nomes-para-a-mesma-lista)

Criar linhas independentes

Explica por que \[\[0\] \* 3\] \* 2 não permite alterar uma célula de uma linha sem afetar a outra. Escreve uma construção correta.

Primeira pista

A repetição da lista exterior repete referências.

Mais uma pista

É preciso criar a linha dentro de cada iteração, em vez de a repetir depois.

Ver solução

A primeira expressão cria uma linha e refere-a duas vezes. A compreensão executa \[0\] \* 3 em cada iteração e cria duas linhas independentes.

Confere a tua resposta:

*   Identifiquei que as duas posições exteriores referem a mesma lista interior.
*   Usei \[\[0\] \* 3 for \_ in range(2)\].
*   Conferi que alterar matriz\[0\]\[0\] não muda matriz\[1\]\[0\].

#### Erros frequentes

Dizer apenas que Python não suporta matrizes ou fazer uma cópia superficial da lista exterior.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/ct-iadp/listas-tuplos-strings/#dois-nomes-para-a-mesma-lista)

Reconhecer linhas partilhadas

m = \[\[0, 0\]\] \* 2; m\[0\]\[1\] = 7. Quanto vale m\[1\]\[1\]?

Primeira pista

A multiplicação repete referências à lista interior.

Mais uma pista

As duas posições de m referem a mesma linha.

Ver solução

O valor é 7. A alteração afeta o único objeto de linha. Para linhas independentes, usa \[\[0, 0\] for \_ in range(2)\].

#### Erros frequentes

Confundir repetir uma referência com criar uma cópia de cada linha.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/ct-iadp/listas-tuplos-strings/#vetores-e-matrizes-com-listas)
