Closed
Description
Related: #4039 (where this started to become an issue), #4202, #4830, #4628, #4718, #4628.
Very simple: both indices get an _id
property that can be compared with is
and is reset every time an object is created, so it only stays set when set explicitly (like in view(), but not in copy()). Adds an is_
method that wraps this for external use and makes it so you don't need hasattr
checks, etc.
>>> ind = Index(range(10))
>>> ind.is_(ind)
True
>>> ind.is_(Index(range(10)))
False
>>> ind.is_(ind.view().view().view().view())
True
>>> ind.is_(ind.copy())
False
>>> ind.is_(ind.copy(deep=False))
False
>>> ind.is_(ind[:])
False
>>> ind.is_(ind.view(np.ndarray).view(Index))
False
>>> ind.is_(np.array(range(10)))
False
>>> ind.is_(ind.view().base) # quasi-implementation dependent
True
>>> ind2 = ind.view()
>>> ind2.name = 'bob'
>>> ind.is_(ind2)
True
>>> ind2.is_(ind)
True
>>> # doesn't matter if Indices are *actually* views of underlying data, e.g.
>>> ind.is_(Index(ind.values))
False
>>> arr = np.array(range(1, 11))
>>> ind1 = Index(arr, copy=False)
>>> ind2 = Index(arr, copy=False)
>>> ind1.is_(ind2)
False
MultiIndex behavior (same behavior for set labels and set levels)
>>> mi = MultiIndex.from_tuples(zip(range(10), range(10)))
>>> mi.is_(mi)
True
>>> mi.is_(mi.view())
True
>>> mi.is_(mi.view().view().view().view())
True
>>> mi2 = mi.view()
>>> mi2.names = ["A", "B"]
>>> mi2.is_(mi)
True
>>> mi.is_(mi2)
True
>>> mi.is_(mi.set_names(["C", "D"]))
True
>>> mi3 = mi2.set_levels([range(10), range(10)])
>>> mi3.is_(mi2)
False
>>> mi4 = mi3.view()
>>> mi4.set_levels([[1 for _ in range(10)], range(10)], inplace=True)
>>> mi4.is_(mi3)
False
>>> mi5 = mi.view()
>>> mi5.set_levels(mi5.levels, inplace=True)
>>> mi5.is_(mi)
False
Could make it easier to resolve #4013.