Сравнение идентификаторов объектов двух пустых массивов - PullRequest
0 голосов
/ 11 февраля 2019

Я уже давно пользуюсь numpy, но наткнулся на одну вещь, которую я не до конца понял:

a = np.ones(20)
b = np.zeros(10)

print(id(a)==id(b))          # prints False
print(id(a), id(b))          # prints (4591424976, 4590843504)

print(id(a[0])==id(b[0]))    # prints True 
print(id(a[0]), id(b[0]))    # prints (4588947064, 4588947064)

print(id(a[0]))              # 4588947184
print(id(b[0]))              # 4588947280

Может кто-нибудь объяснить, что наблюдалось в последних четырех утверждениях печати?Кроме того, я знал, что id дает вам уникальный идентификатор объекта, фактически размещенный в памяти, но каждый раз, когда я запускаю последние два оператора печати, я получаю разные значения id.Это ожидаемое поведение?

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Важно отметить, что все в Python является объектом, даже числа и классы.Вы взяли 2 объекта numpy array, и каждое из них содержит одинаковые значения, т. Е. 0. Когда вы говорите:

print('id of 0 =',id(0))

a = 0
print('id of a =',id(a))

b = a
print('id of b =',id(b))

c = 0.0
print('id of c =',id(c))

В ответ вы получите что-то вроде (ваш случай другой):

id of 0 = 140472391630016
id of a = 140472391630016
id of b = 140472391630016
id of c = 140472372786520

Следовательно, целое число 0 имеет уникальный идентификатор.Идентификатор целого числа 0 остается постоянным в течение всей жизни.Аналогично обстоит дело с float 0.0 и другими объектами.Таким образом, в вашем случае a[0] или b[0] идентификатор объекта с нулем будет оставаться неизменным до тех пор, пока он не будет активен, поскольку оба содержат 0 в качестве значения объекта.Каждый раз, когда вы печатаете a[0] или b[0] в другой строке, вы возвращаете разные идентификаторы объекта, потому что вы запускаете его на другой строке, следовательно, с разным временем жизни.Вы можете попробовать:

print(id(a)==id(b))
print(id(a),id(b))
print(id(a[0])==id(b[0]))
print(id(a[0]),id(b[0]))

Вывод будет:

False
2566443478752 2566448028528
True
2566447961120 2566447961120

Обратите внимание, что вторая строка вернет вам 2 разных идентификатора объекта типа массива numpy, потому что оба - разные списки.

0 голосов
/ 11 февраля 2019

Краткий ответ: вы должны забыть о том, что полагаетесь на id, чтобы попытаться глубже понять работу Python.На его вывод влияют детали реализации cpython, оптимизация глазка и повторное использование памяти.Чаще всего id - это красная сельдь.Это особенно верно для numpy.

В вашем конкретном случае только a и b существуют как объекты python.Когда вы берете элемент a[0], вы создаете новый объект Python, скаляр типа numpy.float64 (или, возможно, numpy.float32 в зависимости от вашей системы).Это новые объекты Python, и поэтому им присваиваются новые id, , если только интерпретатор не поймет, что вы пытаетесь использовать этот объект дважды (это, вероятно, происходит в вашем среднем примере, хотя я нахожуУдивительно, что двум numpy.float64 объектам с разными значениями присваивается один и тот же id. Но странная магия исчезнет, ​​если сначала назначить a[0] и b[0] собственным именам, так что это, вероятно, связано с некоторой оптимизацией).Может также случиться, что интерпретатор повторно использует адреса памяти, давая вам id s, которые появились раньше.

Просто чтобы увидеть, как бесполезно id с numpy, даже тривиальные представления - это новые объекты python сновые id с, хотя для всех намерений и целей они так же хороши, как и оригинал:

>>> arr = np.arange(3)

>>> id(arr)
140649669302992

>>> id(arr[...])
140649669667056

А вот пример для id повторного использования в интерактивной оболочке:

>>> id(np.arange(3))
140649669027120

>>> id(np.arange(3))
140649669028480

>>> id(np.arange(3))
140649669026480

Конечно, нет такой вещи, как int интернирование для массивов numpy, так что вышеизложенное только из-за того, что интерпретатор повторно использует id s.Тот факт, что id возвращает адрес памяти, опять-таки просто деталь реализации cpython.Забудьте о id.

Единственное, что вы можете использовать с numpy, это numpy.may_share_memory и numpy.shares_memory.

...