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 ,
@@ -457,6 +460,8 @@ def _engine_type(
457
460
458
461
str = CachedAccessor ("str" , StringMethods )
459
462
463
+ _references = None
464
+
460
465
# --------------------------------------------------------------------
461
466
# Constructors
462
467
@@ -477,6 +482,10 @@ def __new__(
477
482
478
483
data_dtype = getattr (data , "dtype" , None )
479
484
485
+ refs = None
486
+ if not copy and isinstance (data , (ABCSeries , Index )):
487
+ refs = data ._references
488
+
480
489
# range
481
490
if isinstance (data , (range , RangeIndex )):
482
491
result = RangeIndex (start = data , copy = copy , name = name )
@@ -550,7 +559,7 @@ def __new__(
550
559
klass = cls ._dtype_to_subclass (arr .dtype )
551
560
552
561
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 )
554
563
555
564
@classmethod
556
565
def _ensure_array (cls , data , dtype , copy : bool ):
@@ -629,7 +638,7 @@ def _dtype_to_subclass(cls, dtype: DtypeObj):
629
638
630
639
@classmethod
631
640
def _simple_new (
632
- cls : type [_IndexT ], values : ArrayLike , name : Hashable = None
641
+ cls : type [_IndexT ], values : ArrayLike , name : Hashable = None , refs = None
633
642
) -> _IndexT :
634
643
"""
635
644
We require that we have a dtype compat for the values. If we are passed
@@ -644,6 +653,9 @@ def _simple_new(
644
653
result ._name = name
645
654
result ._cache = {}
646
655
result ._reset_identity ()
656
+ result ._references = refs
657
+ if refs is not None :
658
+ refs .add_index_reference (result )
647
659
648
660
return result
649
661
@@ -740,13 +752,13 @@ def _shallow_copy(self: _IndexT, values, name: Hashable = no_default) -> _IndexT
740
752
"""
741
753
name = self ._name if name is no_default else name
742
754
743
- return self ._simple_new (values , name = name )
755
+ return self ._simple_new (values , name = name , refs = self . _references )
744
756
745
757
def _view (self : _IndexT ) -> _IndexT :
746
758
"""
747
759
fastpath to make a shallow copy, i.e. new object with same data.
748
760
"""
749
- result = self ._simple_new (self ._values , name = self ._name )
761
+ result = self ._simple_new (self ._values , name = self ._name , refs = self . _references )
750
762
751
763
result ._cache = self ._cache
752
764
return result
@@ -956,7 +968,7 @@ def view(self, cls=None):
956
968
# of types.
957
969
arr_cls = idx_cls ._data_cls
958
970
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 )
960
972
961
973
result = self ._data .view (cls )
962
974
else :
@@ -1012,7 +1024,15 @@ def astype(self, dtype, copy: bool = True):
1012
1024
new_values = astype_array (values , dtype = dtype , copy = copy )
1013
1025
1014
1026
# 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
1016
1036
1017
1037
_index_shared_docs [
1018
1038
"take"
@@ -5155,7 +5175,9 @@ def __getitem__(self, key):
5155
5175
# pessimization com.is_bool_indexer and ndim checks.
5156
5176
result = getitem (key )
5157
5177
# 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
+ )
5159
5181
5160
5182
if com .is_bool_indexer (key ):
5161
5183
# if we have list[bools, length=1e5] then doing this check+convert
@@ -5181,7 +5203,7 @@ def _getitem_slice(self: _IndexT, slobj: slice) -> _IndexT:
5181
5203
Fastpath for __getitem__ when we know we have a slice.
5182
5204
"""
5183
5205
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 )
5185
5207
5186
5208
@final
5187
5209
def _can_hold_identifiers_and_holds_name (self , name ) -> bool :
@@ -6700,7 +6722,11 @@ def infer_objects(self, copy: bool = True) -> Index:
6700
6722
)
6701
6723
if copy and res_values is values :
6702
6724
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
6704
6730
6705
6731
# --------------------------------------------------------------------
6706
6732
# Generated Arithmetic, Comparison, and Unary Methods
0 commit comments