73
73
rewrite_exception ,
74
74
)
75
75
76
- from pandas .core .dtypes .astype import astype_array
76
+ from pandas .core .dtypes .astype import (
77
+ astype_array ,
78
+ astype_is_view ,
79
+ )
77
80
from pandas .core .dtypes .cast import (
78
81
LossySetitemError ,
79
82
can_hold_element ,
@@ -458,6 +461,8 @@ def _engine_type(
458
461
459
462
str = CachedAccessor ("str" , StringMethods )
460
463
464
+ _references = None
465
+
461
466
# --------------------------------------------------------------------
462
467
# Constructors
463
468
@@ -478,6 +483,10 @@ def __new__(
478
483
479
484
data_dtype = getattr (data , "dtype" , None )
480
485
486
+ refs = None
487
+ if not copy and isinstance (data , (ABCSeries , Index )):
488
+ refs = data ._references
489
+
481
490
# range
482
491
if isinstance (data , (range , RangeIndex )):
483
492
result = RangeIndex (start = data , copy = copy , name = name )
@@ -551,7 +560,7 @@ def __new__(
551
560
klass = cls ._dtype_to_subclass (arr .dtype )
552
561
553
562
arr = klass ._ensure_array (arr , arr .dtype , copy = False )
554
- return klass ._simple_new (arr , name )
563
+ return klass ._simple_new (arr , name , refs = refs )
555
564
556
565
@classmethod
557
566
def _ensure_array (cls , data , dtype , copy : bool ):
@@ -629,7 +638,7 @@ def _dtype_to_subclass(cls, dtype: DtypeObj):
629
638
# See each method's docstring.
630
639
631
640
@classmethod
632
- def _simple_new (cls , values : ArrayLike , name : Hashable = None ) -> Self :
641
+ def _simple_new (cls , values : ArrayLike , name : Hashable = None , refs = None ) -> Self :
633
642
"""
634
643
We require that we have a dtype compat for the values. If we are passed
635
644
a non-dtype compat, then coerce using the constructor.
@@ -643,6 +652,9 @@ def _simple_new(cls, values: ArrayLike, name: Hashable = None) -> Self:
643
652
result ._name = name
644
653
result ._cache = {}
645
654
result ._reset_identity ()
655
+ result ._references = refs
656
+ if refs is not None :
657
+ refs .add_index_reference (result )
646
658
647
659
return result
648
660
@@ -739,13 +751,13 @@ def _shallow_copy(self, values, name: Hashable = no_default) -> Self:
739
751
"""
740
752
name = self ._name if name is no_default else name
741
753
742
- return self ._simple_new (values , name = name )
754
+ return self ._simple_new (values , name = name , refs = self . _references )
743
755
744
756
def _view (self ) -> Self :
745
757
"""
746
758
fastpath to make a shallow copy, i.e. new object with same data.
747
759
"""
748
- result = self ._simple_new (self ._values , name = self ._name )
760
+ result = self ._simple_new (self ._values , name = self ._name , refs = self . _references )
749
761
750
762
result ._cache = self ._cache
751
763
return result
@@ -955,7 +967,7 @@ def view(self, cls=None):
955
967
# of types.
956
968
arr_cls = idx_cls ._data_cls
957
969
arr = arr_cls (self ._data .view ("i8" ), dtype = dtype )
958
- return idx_cls ._simple_new (arr , name = self .name )
970
+ return idx_cls ._simple_new (arr , name = self .name , refs = self . _references )
959
971
960
972
result = self ._data .view (cls )
961
973
else :
@@ -1011,7 +1023,15 @@ def astype(self, dtype, copy: bool = True):
1011
1023
new_values = astype_array (values , dtype = dtype , copy = copy )
1012
1024
1013
1025
# pass copy=False because any copying will be done in the astype above
1014
- return Index (new_values , name = self .name , dtype = new_values .dtype , copy = False )
1026
+ result = Index (new_values , name = self .name , dtype = new_values .dtype , copy = False )
1027
+ if (
1028
+ not copy
1029
+ and self ._references is not None
1030
+ and astype_is_view (self .dtype , dtype )
1031
+ ):
1032
+ result ._references = self ._references
1033
+ result ._references .add_index_reference (result )
1034
+ return result
1015
1035
1016
1036
_index_shared_docs [
1017
1037
"take"
@@ -5183,7 +5203,7 @@ def _getitem_slice(self, slobj: slice) -> Self:
5183
5203
Fastpath for __getitem__ when we know we have a slice.
5184
5204
"""
5185
5205
res = self ._data [slobj ]
5186
- result = type (self )._simple_new (res , name = self ._name )
5206
+ result = type (self )._simple_new (res , name = self ._name , refs = self . _references )
5187
5207
if "_engine" in self ._cache :
5188
5208
reverse = slobj .step is not None and slobj .step < 0
5189
5209
result ._engine ._update_from_sliced (self ._engine , reverse = reverse ) # type: ignore[union-attr] # noqa: E501
@@ -6707,7 +6727,11 @@ def infer_objects(self, copy: bool = True) -> Index:
6707
6727
)
6708
6728
if copy and res_values is values :
6709
6729
return self .copy ()
6710
- return Index (res_values , name = self .name )
6730
+ result = Index (res_values , name = self .name )
6731
+ if not copy and res_values is values and self ._references is not None :
6732
+ result ._references = self ._references
6733
+ result ._references .add_index_reference (result )
6734
+ return result
6711
6735
6712
6736
# --------------------------------------------------------------------
6713
6737
# Generated Arithmetic, Comparison, and Unary Methods
0 commit comments