Определить разницу между объектами Python - PullRequest
0 голосов
/ 01 ноября 2018

Предположим, у меня есть:

tup1 = ((100,), (100,))
tup2 = tuple(map(tuple, np.array([100, 100]).reshape(-1,1)))

Теперь tup1 == tup2 возвращает True (что, как я понимаю, происходит из структурного равенства).

Однако, как часть какого-то проекта на Python, я пытаюсь сделать следующее:

from comtypes.automation import (byref, windll, 
    POINTER, VARIANT, PyDLL, py_object, wintypes)

_dll = PyDLL(pythoncom.__file__) 
_pack = _dll.PyCom_VariantFromPyObject
_pack.argtypes = py_object, POINTER(VARIANT) 
_pack.restype = wintypes.BOOL

Теперь

_pack(tup1, VARIANT())

работает, пока

_pack(tup2, VARIANT())

выдает исключение. Чем на самом деле отличаются tup1 и tup2 (помимо указания на разные адреса в памяти), которые могут вызвать это

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

tup1 == tup2 может быть истиной, но типы не идентичны. Попробуйте следующее и убедитесь сами:

[[type(dt) for dt in t] for t in tup1]

и

[[type(dt) for dt in t] for t in tup2]
0 голосов
/ 01 ноября 2018

Каждый тип объекта может определять равенство в своих собственных терминах. Кортежи равны, если они имеют одинаковую длину, а их содержимое проверяется как равное. Тест содержимого одинаков, поскольку оба они также являются кортежами, каждый из которых при сопоставлении равен тесту.

Но хотя целочисленные значения в теста вложенных кортежей равны, они не совпадают с типом . Целые числа проверяют равенство по числовому значению, поэтому 1 == 1.0 также имеет значение true, хотя один объект является целым числом, а другой - плавающим. В том же духе tup1[0][0] == tup2[0][0] верно, потому что обе стороны имеют одинаковое числовое значение 100.

И хотя у первого кортежа есть объекты Python int, у второго нет. Вместо этого у вас есть numpy определенный целочисленный тип здесь:

>>> import numpy as np
>>> tup2 = tuple(map(tuple, np.array([100, 100]).reshape(-1,1)))
>>> tup2[0][0]
100
>>> type(tup2[0][0])
<class 'numpy.int64'>

Это трудно увидеть, поскольку представление значения выглядит точно так же, как и для типа Python int, но для этого конкретного вызова C API, который вы делаете, numpy.int64 не распознается как приемлемый тип.

Вам нужно преобразовать эти int64 объекты обратно в стандартные целые числа Python:

>>> int(tup2[0][0])
100
>>> type(int(tup2[0][0]))
<class 'int'>

На самом деле вы можете указать массиву numpy сделать это за вас, если вы используете array.tolist():

>>> np.array([100, 100]).reshape(-1,1).tolist()
[[100], [100]]
>>> type(np.array([100, 100]).reshape(-1,1).tolist()[0][0])
<class 'int'>

Из array.tolist() документации:

Возвращает копию данных массива в виде (вложенного) списка Python. Элементы данных преобразуются в ближайший совместимый тип Python.

(жирный акцент мой).

Создайте свои кортежи оттуда:

tup2 = tuple(map(tuple, np.array([100, 100]).reshape(-1,1).tolist()))

Хотя .tolist() предоставляет вам (вложенную) структуру списка эквивалентов типов Python, вы также можете получить отдельные значения с помощью метода numpy.item() , если вам нужен эффективный доступ к таким значениям из существующий массив.

...