NumPy: Cópias e Views

Última atualização: 2026-08-26

Charlie modificou um sub-array e descobriu que o original também havia mudado — ele gastou 2 horas depurando. Alice diz: "Verifique o atributo .base. Se base is o array original, é uma view. Na dúvida, .copy()."

Esta história destaca um problema crítico: nem todas as operações NumPy retornam arrays independentes. Entender a diferença entre views e cópias é essencial para evitar bugs sutis de modificação de dados.


1. O Mecanismo de View

(1) O Que É uma View

Uma view é outra "janela" para o array original — ela compartilha a mesma memória. Modificar uma view modifica diretamente o array original.

PYTHON
import numpy as np

a = np.array([1, 2, 3, 4, 5])
b = a[1:4]          # fatia retorna uma view
b[0] = 999
print(a)            # [  1 999   3   4   5]  original mudou!
print(b)            # [999   3   4]
TEXT 📖 Somente leitura
> **Output:** Execute o NumPy 2.x em seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem o NumPy pré-instalado — instale-o localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.

A vantagem das views é zero-copy — sem memória extra, extremamente rápido.

(2) Relação de Memória

PYTHON
a = np.array([10, 20, 30])
b = a[:]            # view
print(a.__array_interface__['data'][0])  # endereço de dados original
print(b.__array_interface__['data'][0])  # endereço de dados da view (mesmo!)
TEXT 📖 Somente leitura
> **Output:** Execute o NumPy 2.x em seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem o NumPy pré-instalado — instale-o localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.

Ambos apontam para o mesmo endereço inicial de memória — apenas os metadados (shape, strides) diferem.

(3) O Atributo .base

PYTHON
a = np.arange(12).reshape(3, 4)
b = a[0:2, 1:3]  # fatia view
c = a[[0, 2]]    # indexação fancy — cópia

print(b.base is a)  # True — view
print(c.base is a)  # False — cópia


2. Quais Operações Retornam Views vs Cópias

(1) Views (memória compartilhada, sem cópia)

Operação Exemplo
Fatiamento básico a[1:5], a[1:5:2], a[:, 2:4]
.view() a.view(np.float32)
reshape a.reshape(3, 4)
transpose / .T a.T, a.transpose(1, 0)
ravel (geralmente) a.ravel()
squeeze a.squeeze()
newaxis a[:, np.newaxis]

(2) Cópias (nova memória, independente)

Operação Exemplo
.copy() a.copy()
Indexação fancy a[[0, 2, 4]]
Indexação booleana a[a > 0]
astype a.astype(np.float32)
flatten a.flatten()
np.where np.where(a > 0, a, 0)

▶ Exemplo

TEXT 📖 Somente leitura
> **Output:** Execute o NumPy 2.x em seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem o NumPy pré-instalado — instale-o localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.

: Verificar view vs copy com .base (Dificuldade ⭐)

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)

# Fatia básica — view
b = a[0:2]
print(f"slice base is a: {b.base is a}")  # True

# Reshape — view
c = a.reshape(6, 2)
print(f"reshape base is a: {c.base is a}")  # True

# Indexação fancy — cópia
d = a[[0, 2]]
print(f"fancy base is a: {d.base is a}")  # False

# Indexação booleana — cópia
e = a[a > 5]
print(f"boolean base is a: {e.base is a}")  # False
TEXT 📖 Somente leitura
> **Output:** Execute o NumPy 2.x em seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem o NumPy pré-instalado — instale-o localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
⚠️ Nota: O código abaixo precisa ser executado em um ambiente Python local.



3. Tabelas Comparativas

(1) Árvore de Decisão View vs Cópia

TEXT 📖 Somente leitura
É uma fatia básica (start:stop:step)?
  ├── Sim → View (memória compartilhada)
  └── Não → É indexação fancy/booleana?
      ├── Sim → Cópia (nova memória)
      └── Não → Verifique atributo .base

(2) Impacto no Desempenho

Operação Tempo (1M elementos) Memória
View (fatia) O(1) Compartilhada
Cópia (fancy) O(n) Nova alocação
.copy() O(n) Nova alocação
astype O(n) Nova alocação

▶ Exemplo: Reshape e transpose retornam views (Dificuldade ⭐⭐)

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)

# Reshape retorna uma view
b = a.reshape(6, 2)
print(f"reshape base is a: {b.base is a}")

# Transpose retorna uma view
c = a.T
print(f"transpose base is a: {c.base is a}")

# Modificar a view altera o original
c[0, 0] = 999
print(f"a[0, 0] after transpose mod: {a[0, 0]}")

Output:

TEXT 📖 Somente leitura
reshape base is a: True
transpose base is a: True
a[0, 0] after transpose mod: 999

▶ Exemplo: flatten vs ravel — cópia vs view (Dificuldade ⭐⭐)

PYTHON
import numpy as np

a = np.arange(12).reshape(3, 4)

# ravel geralmente retorna uma view
r = a.ravel()
print(f"ravel base is a: {r.base is a}")

# flatten sempre retorna uma cópia
f = a.flatten()
print(f"flatten base is a: {f.base is a}")

# Após transpose, ravel pode precisar copiar
t = a.T
r2 = t.ravel()
print(f"ravel of transposed base is a: {r2.base is a}")

Output:

TEXT 📖 Somente leitura
ravel base is a: True
flatten base is a: False
ravel of transposed base is a: False


❓ Perguntas Frequentes

P: Como verifico se um array é uma view de outro? R: Verifique arr.base is original. Se True, é uma view. Se arr.base é None, ele possui seus próprios dados.

P: Posso criar uma view com um dtype diferente? R: Sim — a.view(np.float32) reinterpreta os mesmos bytes como um tipo diferente. Isso é perigoso e raramente necessário. Use astype para uma cópia segura com conversão.

P: Por que ravel às vezes retorna uma cópia? R: ravel retorna uma view apenas se o array for contíguo na memória. Após operações como transpose, o array pode ser não-contíguo, e ravel recorre a uma cópia.

P: Quando devo usar .copy()? R: (1) Quando você vai modificar um sub-array e não quer afetar o original, (2) quando precisa de um array contíguo para uma operação em nível C, (3) quando quer quebrar o link de memória explicitamente.


📖 Resumo



📝 Exercícios

  1. Básico (Dificuldade ⭐): Crie um array 1D de 10 elementos. Crie uma fatia, uma indexação fancy e uma seleção por máscara booleana. Para cada uma, verifique se modificar o resultado altera o original.

  2. Intermediário (Dificuldade ⭐⭐): Crie um array 3x4, pegue uma fatia 2x2 e modifique-a. Observe o original mudando. Agora use .copy() e repita — confirme que o original permanece inalterado.

  3. Desafio (Dificuldade ⭐⭐⭐): Crie um array 3D, transponha-o, depois tente fazer reshape do resultado. Verifique se o reshape retorna uma view (use .base). Explique por quê ou por quê não.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%