Repository: pandas-dev/pandas (python)

Issue:
BUG: Series.replace(dict-like, dict-like) raises uninformative AttributeError
### Pandas version checks

- [X] I have checked that this issue has not already been reported.

- [X] I have confirmed this bug exists on the [latest version](https://pandas.pydata.org/docs/whatsnew/index.html) of pandas.

- [X] I have confirmed this bug exists on the [main branch](https://pandas.pydata.org/docs/dev/getting_started/install.html#installing-the-development-version-of-pandas) of pandas.


### Reproducible Example

```python
In [2]: pd.Series([1, 2]).replace(pd.Series([1]), pd.Series([2]))
AttributeError: 'Series' object has no attribute '_replace_columnwise'
```


### Issue Description

It appears `.replace(dict-like, dict-like)` is only valid if the original object is a `DataFrame` so this should probably raise a `ValueError` instead of raising an `AttributeError`

### Expected Behavior

Raise a `ValueError`

### Installed Versions

<details>

Replace this line with the output of pd.show_versions()

</details>


Pull request description:
Series replace error
- [ ] closes #59452 
- [ ] [Tests added and passed](https://github.com/pandas-dev/pandas/blob/main/pandas/tests/series/methods/test_replace.py) 
- [ ] Added an entry in the latest `doc/source/whatsnew/v3.0.0.rst`


Patch:
diff --git a/pandas/core/generic.py b/pandas/core/generic.py
index 8cccb7001e..8e2524c21d 100644
--- a/pandas/core/generic.py
+++ b/pandas/core/generic.py
@@ -7487,9 +7487,13 @@ class NDFrame(PandasObject, indexing.IndexingMixin):
                 if inplace:
                     return None
                 return self.copy(deep=False)
-
             if is_dict_like(to_replace):
                 if is_dict_like(value):  # {'A' : NA} -> {'A' : 0}
+                    if isinstance(self, ABCSeries):
+                        raise ValueError(
+                            "to_replace and value cannot be dict-like for "
+                            "Series.replace"
+                        )
                     # Note: Checking below for `in foo.keys()` instead of
                     #  `in foo` is needed for when we have a Series and not dict
                     mapping = {


Test patch:
diff --git a/pandas/tests/series/methods/test_replace.py b/pandas/tests/series/methods/test_replace.py
index de0855bf71..611fcc114d 100644
--- a/pandas/tests/series/methods/test_replace.py
+++ b/pandas/tests/series/methods/test_replace.py
@@ -496,6 +496,15 @@ class TestSeriesReplace:
         with pytest.raises(ValueError, match=msg):
             ser.replace(to_replace, value)
 
+    def test_replace_dict_like_with_dict_like(self):
+        # GH 59452
+        s = pd.Series([1, 2, 3, 4, 5])
+        to_replace = pd.Series([1])
+        value = pd.Series([75])
+        msg = "to_replace and value cannot be dict-like for Series.replace"
+        with pytest.raises(ValueError, match=msg):
+            s.replace(to_replace, value)
+
     def test_replace_extension_other(self, frame_or_series):
         # https://github.com/pandas-dev/pandas/issues/34530
         obj = frame_or_series(pd.array([1, 2, 3], dtype="Int64"))