7373 rewrite_exception ,
7474)
7575
76- from pandas .core .dtypes .astype import astype_array
76+ from pandas .core .dtypes .astype import (
77+ astype_array ,
78+ astype_is_view ,
79+ )
7780from pandas .core .dtypes .cast import (
7881 LossySetitemError ,
7982 can_hold_element ,
@@ -457,6 +460,8 @@ def _engine_type(
457460
458461 str = CachedAccessor ("str" , StringMethods )
459462
463+ _references = None
464+
460465 # --------------------------------------------------------------------
461466 # Constructors
462467
@@ -477,6 +482,10 @@ def __new__(
477482
478483 data_dtype = getattr (data , "dtype" , None )
479484
485+ refs = None
486+ if not copy and isinstance (data , (ABCSeries , Index )):
487+ refs = data ._references
488+
480489 # range
481490 if isinstance (data , (range , RangeIndex )):
482491 result = RangeIndex (start = data , copy = copy , name = name )
@@ -550,7 +559,7 @@ def __new__(
550559 klass = cls ._dtype_to_subclass (arr .dtype )
551560
552561 arr = klass ._ensure_array (arr , arr .dtype , copy = False )
553- return klass ._simple_new (arr , name )
562+ return klass ._simple_new (arr , name , refs = refs )
554563
555564 @classmethod
556565 def _ensure_array (cls , data , dtype , copy : bool ):
@@ -629,7 +638,7 @@ def _dtype_to_subclass(cls, dtype: DtypeObj):
629638
630639 @classmethod
631640 def _simple_new (
632- cls : type [_IndexT ], values : ArrayLike , name : Hashable = None
641+ cls : type [_IndexT ], values : ArrayLike , name : Hashable = None , refs = None
633642 ) -> _IndexT :
634643 """
635644 We require that we have a dtype compat for the values. If we are passed
@@ -644,6 +653,9 @@ def _simple_new(
644653 result ._name = name
645654 result ._cache = {}
646655 result ._reset_identity ()
656+ result ._references = refs
657+ if refs is not None :
658+ refs .add_index_reference (result )
647659
648660 return result
649661
@@ -740,13 +752,13 @@ def _shallow_copy(self: _IndexT, values, name: Hashable = no_default) -> _IndexT
740752 """
741753 name = self ._name if name is no_default else name
742754
743- return self ._simple_new (values , name = name )
755+ return self ._simple_new (values , name = name , refs = self . _references )
744756
745757 def _view (self : _IndexT ) -> _IndexT :
746758 """
747759 fastpath to make a shallow copy, i.e. new object with same data.
748760 """
749- result = self ._simple_new (self ._values , name = self ._name )
761+ result = self ._simple_new (self ._values , name = self ._name , refs = self . _references )
750762
751763 result ._cache = self ._cache
752764 return result
@@ -956,7 +968,7 @@ def view(self, cls=None):
956968 # of types.
957969 arr_cls = idx_cls ._data_cls
958970 arr = arr_cls (self ._data .view ("i8" ), dtype = dtype )
959- return idx_cls ._simple_new (arr , name = self .name )
971+ return idx_cls ._simple_new (arr , name = self .name , refs = self . _references )
960972
961973 result = self ._data .view (cls )
962974 else :
@@ -1012,7 +1024,15 @@ def astype(self, dtype, copy: bool = True):
10121024 new_values = astype_array (values , dtype = dtype , copy = copy )
10131025
10141026 # pass copy=False because any copying will be done in the astype above
1015- return Index (new_values , name = self .name , dtype = new_values .dtype , copy = False )
1027+ result = Index (new_values , name = self .name , dtype = new_values .dtype , copy = False )
1028+ if (
1029+ not copy
1030+ and self ._references is not None
1031+ and astype_is_view (self .dtype , dtype )
1032+ ):
1033+ result ._references = self ._references
1034+ result ._references .add_index_reference (result )
1035+ return result
10161036
10171037 _index_shared_docs [
10181038 "take"
@@ -5155,7 +5175,9 @@ def __getitem__(self, key):
51555175 # pessimization com.is_bool_indexer and ndim checks.
51565176 result = getitem (key )
51575177 # Going through simple_new for performance.
5158- return type (self )._simple_new (result , name = self ._name )
5178+ return type (self )._simple_new (
5179+ result , name = self ._name , refs = self ._references
5180+ )
51595181
51605182 if com .is_bool_indexer (key ):
51615183 # if we have list[bools, length=1e5] then doing this check+convert
@@ -5181,7 +5203,7 @@ def _getitem_slice(self: _IndexT, slobj: slice) -> _IndexT:
51815203 Fastpath for __getitem__ when we know we have a slice.
51825204 """
51835205 res = self ._data [slobj ]
5184- return type (self )._simple_new (res , name = self ._name )
5206+ return type (self )._simple_new (res , name = self ._name , refs = self . _references )
51855207
51865208 @final
51875209 def _can_hold_identifiers_and_holds_name (self , name ) -> bool :
@@ -6700,7 +6722,11 @@ def infer_objects(self, copy: bool = True) -> Index:
67006722 )
67016723 if copy and res_values is values :
67026724 return self .copy ()
6703- return Index (res_values , name = self .name )
6725+ result = Index (res_values , name = self .name )
6726+ if not copy and res_values is values and self ._references is not None :
6727+ result ._references = self ._references
6728+ result ._references .add_index_reference (result )
6729+ return result
67046730
67056731 # --------------------------------------------------------------------
67066732 # Generated Arithmetic, Comparison, and Unary Methods
0 commit comments