Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REF: avoid mutating Series._values directly in setitem but defer to Manager method #41879

8 changes: 8 additions & 0 deletions pandas/core/internals/array_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,14 @@ def apply(self, func, **kwargs):
return type(self)([new_array], self._axes)

def setitem(self, indexer, value):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you type annotate the return values at the very least on these (Any is fine) just indicative

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an existing method, all other Manager methods with general indexer argument are not yet typed, so I would prefer to leave that for a typing-specific PR (I also thought that we generally want to avoid adding Any for "not yet typed" unless it's really "any").

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kk

"""
Set values with indexer.

For SingleArrayManager, this backs s[indexer] = value

See `setitem_inplace` for a version that works inplace and doesn't
return a new Manager.
"""
return self.apply_with_block("setitem", indexer=indexer, value=value)

def idelete(self, indexer) -> SingleArrayManager:
Expand Down
12 changes: 12 additions & 0 deletions pandas/core/internals/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,18 @@ def array(self):
"""
return self.arrays[0] # type: ignore[attr-defined]

def setitem_inplace(self, indexer, value) -> None:
"""
Set values with indexer.

For Single[Block/Array]Manager, this backs s[indexer] = value

This is an inplace version of `setitem()`, mutating the manager/values
in place, not returning a new Manager (and Block), and thus never changing
the dtype.
"""
self.array[indexer] = value


def interleaved_dtype(dtypes: list[DtypeObj]) -> DtypeObj | None:
"""
Expand Down
5 changes: 5 additions & 0 deletions pandas/core/internals/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,11 @@ def where(self: T, other, cond, align: bool, errors: str) -> T:
)

def setitem(self: T, indexer, value) -> T:
"""
Set values with indexer.

For SingleBlockManager, this backs s[indexer] = value
"""
return self.apply("setitem", indexer=indexer, value=value)

def putmask(self, mask, new, align: bool = True):
Expand Down
7 changes: 4 additions & 3 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -1061,7 +1061,6 @@ def __setitem__(self, key, value) -> None:
try:
self._set_with_engine(key, value)
except (KeyError, ValueError):
values = self._values
if is_integer(key) and self.index.inferred_type != "integer":
# positional setter
if not self.index._should_fallback_to_positional:
Expand All @@ -1075,7 +1074,8 @@ def __setitem__(self, key, value) -> None:
FutureWarning,
stacklevel=2,
)
values[key] = value
# this is equivalent to self._values[key] = value
self._mgr.setitem_inplace(key, value)
else:
# GH#12862 adding a new key to the Series
self.loc[key] = value
Expand Down Expand Up @@ -1107,7 +1107,8 @@ def _set_with_engine(self, key, value) -> None:
# error: Argument 1 to "validate_numeric_casting" has incompatible type
# "Union[dtype, ExtensionDtype]"; expected "dtype"
validate_numeric_casting(self.dtype, value) # type: ignore[arg-type]
self._values[loc] = value
# this is equivalent to self._values[key] = value
self._mgr.setitem_inplace(loc, value)

def _set_with(self, key, value):
# other: fancy integer or otherwise
Expand Down