简体   繁体   中英

Determine difference between python objects

Suppose I have:

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

Now tup1 == tup2 returns True (which I realize comes from structural equality).

However, as part of some python project I'm trying to do the following:

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

Now

_pack(tup1, VARIANT())

works while

_pack(tup2, VARIANT())

throws an exception. In what ways do tup1 and tup2 actually differ (apart from pointing to different addresses in memory) that can cause this

Each type of object can define equality in their own terms. Tuples are equal when they have the same length and their contents are tested as equal. The contents test equal because both are also tuples that each test equal when paired up.

But while the integer values in the nested tuples test equal, they are not the same type . Integers test equality on numeric value, so 1 == 1.0 also is true, even though one object is an integer, the other a float. In the same vein, tup1[0][0] == tup2[0][0] is true because both sides have the same numeric value of 100.

And while the first tuple has Python int objects, your second tuple does not. Instead, you have a numpy specific integer type here:

>>> 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'>

This is hard to see as the representation for the value looks exactly the same as for a Python int type, but for that specific C API call you are making, numpy.int64 is not recognised as an acceptable type.

You'd need to convert those int64 objects back to standard Python integers:

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

You can actually tell the numpy array to do this for you if you use 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'>

From the array.tolist() documentation:

Return a copy of the array data as a (nested) Python list. Data items are converted to the nearest compatible Python type.

(bold emphasis mine).

Create your tuples from there:

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

While .tolist() gives you a (nested) list structure of Python type equivalents, you can also get individual values with the numpy.item() method , should you need to have efficient access to such values from an existing array.

tup1 == tup2 may be true, but the types are not identical. Try the following and convince yourself:

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

and

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM