OutrasSecoes / CommonGotchas

Aqui é uma página que irá prover uma discussão sobre os problemas mais comuns encontrado em Python que parecem deixar o usuário novato encucado (tá, o experiente também), juntamente da solução deles. São comumente chamados de 'gotchas', uma forma abreviada de 'got you'. Alguns lhe pegam de surpresa quando você está começando, outros são comportamentos esotéricos (jeito bonito de dizer 'bizarro') do Python.

Atribuição cria referências e não cópias

Isso pode ser um gotcha se você não entender como Python referencia variáveis.

   1 >>>L = [1,2,3]
   2 >>>M = ['X', L, 'Y'] # Coloca uma referência a L
   3 >>>M
   4 ['X', [1, 2, 3], 'Y']
   5 >>>L[1] = 0 # Muda M também
   6 >>>M
   7 ['X', [1, 0 ,3], 'Y']

Solução

Este efeito pode se tornar importante em programas grandes, e algumas vezes referências compartilhadas é exatamente o que você quer. Se não são, você pode evitar isso copiando-os explicitamente; para listas, você pode fazer um cópia top-level usando slice sem limites definido.

   1 >>>L = [1,2,3]
   2 >>>M = ['X', L[:], 'Y'] # Coloca uma cópia de L
   3 >>>M
   4 ['X', [1, 2, 3], 'Y']
   5 >>>L[1] = 0 # Só muda L, não M
   6 >>>M
   7 ['X', [1, 2 ,3], 'Y']
   8 >>>L
   9 [1, 0, 3]

Lembre-se, cópias top-level não copiam listas dentro de listas, por exemplo. Se quiser copiar uma estrutura destas, use o módulo copy padrão.

Repetição adiciona um nível de profundidade

Quando sequências são aninhadas, o efeito pode não ser o que você espera. Veja o exemplo a seguir:

   1 >>>L = [4,5,6]
   2 >>>X = L * 4   # Como [4,5,6] + [4,5,6] + ...
   3 >>>Y = [L] * 4 # Como [L] + [L] + ... = [L, L, ...]
   4 >>>X
   5 [4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6]
   6 >>>Y
   7 [[4, 5, 6], [4, 5, 6], [4, 5, 6], [4, 5, 6]]

Como L foi aninhado na segunda reptição, Y termina colocando referências de volta a lista original referenciada por L e fica passível do mesmo tipo de erro da seção anterior. (ver seção acima)

Solução

A mesma do problema anterior.

Estruturas de dados cíclicas não podem ser impressas

Se um objeto contêm uma referência a ele mesmo, é chamado de um objeto cíclico. Nas versões de Python anterior a 1.5.1, executar 'print' nesses objetos falhava, pois o 'print' do Python não era esperto o suficiente para reconhecer o ciclo (você via o mesmo texto sendo impresso repetidamente, até você parar a execução). Este caso é detectado agora, mas é bom saber: estraturas cíclicas podem fazer seu código cair em loops inesperados.

   1 >>>L = ['oi.']; L.append(L) # Faz um append ao mesmo objeto
   2 >>>L                        # Antes da versão 1.5.1, ocorre um loop infinito

Solução

Simplesmente, não faça isso. Pode haver boas razões para criar ciclos, mas a menos que você tenha código que saiba como manipular isso, você provavelmente não vai querer que seus objetos façam referências a eles mesmos.

Tipos imutáveis não podem ser mudados por índice

NÃO DÁ PRA MUDAR TIPOS IMUTÁVEIS PELO ÍNDICE. :D

   1 T = (1, 2, 3)
   2 T[2] = 4         # erro!
   3 T = T[:2] + (4,) # agora sim!

Solução

Construa um novo objeto com slice, concatenação, etc e retorne o valor ao objeto original. Parece ser trabalho adicional, mas a vantagem é que os efeitos colaterais que atingem listas (mutáveis) não atingem tipos imutáveis como strings e tuplas.

Não espere sempre um resultado

Lembrete: operações como list.append() e list.sort() não retornam valor (tá, retornam None). Chame-as sem atribuir a nenhuma variável. É comum que iniciantes façam operações como:

   1 >>>list = list.append(X)

E pensam que list contém a nova lista. De fato, perderam a referência para 'list', pois 'list' fica com valor 'None'.

OutrasSecoes/CommonGotchas (editada pela última vez em 2008-09-26 14:05:52 por localhost)