В Python, в чем разница между представлением и мелкой копией? - PullRequest
0 голосов
/ 30 мая 2018

В NumPy я понимаю, что нарезка массива дает вам «представление», которое мне кажется точно таким же, как мелкая копия.Чем они отличаются?

1 Ответ

0 голосов
/ 30 мая 2018

В отличие от объекта списка Python, который содержит ссылки на первый уровень объектов элементов (который, в свою очередь, может ссылаться на более глубокие уровни объектов), массив NumPy ссылается только на один буфер данных, в котором хранятся все значения элементов для всех измерениймассив, и нет иерархии объектов элементов за пределами этого буфера данных.

Мелкая копия списка будет содержать копии первого уровня ссылок на элементы и делиться ссылочными объектными элементами с исходным списком.Менее очевидно, что должна содержать поверхностная копия массива NumPy.Должен ли он ( A ) совместно использовать буфер данных с оригиналом или ( B ) иметь свою собственную копию (что фактически делает ее глубокой копией)?

A представление массива NumPy является неглубокой копией в смысле A, то есть он ссылается на тот же буфер данных, что и оригинал, поэтому изменения в исходных данных влияют на данные представления и наоборот.

Библиотечная функция copy.copy () должна создавать поверхностную копию своего аргумента, но при применении к массиву NumPy она создает поверхностную копию в смысле B, то есть новый массив получает свою собственную копиюбуфер данных, поэтому изменения в одном массиве не влияют на другой.

Вот некоторый код, показывающий различные способы копирования / просмотра массивов NumPy:

import numpy as np
import copy

x = np.array([10, 11, 12, 13])

# Create views of x (shallow copies sharing data) in 2 different ways
x_view1 = x.view()
x_view2 = x[:]          # Creates a view using a slice

# Create full copies of x (not sharing data) in 2 different ways
x_copy1 = x.copy()
x_copy2 = copy.copy(x)  # Calls x.__copy__() which creates a full copy of x

# Change some array elements to see what happens
x[0]       = 555        # Affects x, x_view1, and x_view2
x_view1[1] = 666        # Affects x, x_view1, and x_view2
x_view2[2] = 777        # Affects x, x_view1, and x_view2
x_copy1[0] = 888        # Affects only x_copy1
x_copy2[0] = 999        # Affects only x_copy2

print(x)                # [555 666 777  13]
print(x_view1)          # [555 666 777  13]
print(x_view2)          # [555 666 777  13]
print(x_copy1)          # [888  11  12  13]
print(x_copy2)          # [999  11  12  13]

Приведенный выше пример создает представлениявесь диапазон индекса исходного массива и с теми же атрибутами массива, что и у исходного, что не очень интересно (можно заменить простым псевдонимом, например, x_alias = x).Что делает представления мощными, так это то, что они могут быть видами выбранных частей оригинала и иметь разные атрибуты.Это продемонстрировано в следующих нескольких строках кода, которые расширяют приведенный выше пример:

x_view3 = x[::2].reshape(2,1) # Creates a reshaped view of every 2nd element of x
print(x_view3)          # [[555]
                        #  [777]]
x_view3[1] = 333        # Affects 2nd element of x_view3 and 3rd element of x
print(x)                # [555 666 333  13]
print(x_view3)          # [[555]
                        #  [333]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...