`_MultimetricScorer` deals with `_accept_sample_weights` inconsistently

### Describe the bug

When one of the scorers in `_MultimetricScorer` is not a `Scorer` object, it is handled incorrectly.

See line [here](https://github.com/scikit-learn/scikit-learn/blob/0fc081a4e131b08cb6d22f77f250733f265097b4/sklearn/metrics/_scorer.py#L143). If the scorers passed to `MultimetricScorer` are of the following type: [`Scorer`, `function`], it raises an error because the attribute `_accept_sample_weight` does not exist for the second scorer (`function` in this case). This (possibly) bug is present only in 1.7.0 since before this, the `sample_weight` kwarg was being passed to all functions without a check of accepting sample weights.

Possible fix: Use `if hasattr(scorer, '_accept_sample_weight'`) or `if isinstance(scorer, _BaseScorer)` _before_ checking for the `_accept_sample_weight` attribute.

### Steps/Code to Reproduce

```python
import numpy as np
from sklearn.base import BaseEstimator, RegressorMixin
from sklearn.metrics._scorer import _BaseScorer, _MultimetricScorer

# Step 1: Define a simple estimator
class SimpleEstimator(BaseEstimator, RegressorMixin):
    def fit(self, X, y):
        self.mean_ = np.mean(y)
        return self

    def predict(self, X):
        return np.full(X.shape[0], self.mean_)

# Step 2: Define a custom scorer inheriting from _BaseScorer and a function which estimates score
class SimpleScorer(_BaseScorer):
    def _score(self, method_caller, estimator, X, y_true, sample_weight=None):
        y_pred = method_caller(estimator, "predict", X)
        return self._score_func(y_true, y_pred, **self._kwargs)

def default_score(estimator, X, y, sample_weight=None, **kws):
    return estimator.score(X, y, sample_weight=sample_weight)

def mse(y, y_pred):
    return np.mean((y - y_pred)**2)

# Step 3: Create a _MultimetricScorer with multiple scorers
scorers = {
    "mse": SimpleScorer(mse, sign=1, kwargs={}),
    "default": default_score
}
multi_scorer = _MultimetricScorer(scorers=scorers)

# Step 4: Generate sample data
X = np.random.rand(10, 2)
y = np.random.rand(10)
sample_weight = np.random.rand(10)

# Step 5: Fit the estimator and evaluate using the multi-scorer
estimator = SimpleEstimator()
estimator.fit(X, y)
scores = multi_scorer(estimator, X, y, sample_weight=sample_weight)

print("Scores:", scores)
```

### Expected Results

Expected result would be scores for each of the scorers without an error being raised.

### Actual Results

```
AttributeError                            Traceback (most recent call last)
Cell In[6], line 4
      2 estimator = SimpleEstimator()
      3 estimator.fit(X, y)
----> 4 scores = multi_scorer(estimator, X, y, sample_weight=sample_weight)
      6 print("Scores:", scores)

File ~/anaconda3/envs/scoring-311-2/lib/python3.11/site-packages/sklearn/metrics/_scorer.py:144, in _MultimetricScorer.__call__(self, estimator, *args, **kwargs)
    142     if "sample_weight" in kwargs:
    143         for name, scorer in self._scorers.items():
--> 144             if scorer._accept_sample_weight():
    145                 routed_params[name].score["sample_weight"] = kwargs[
    146                     "sample_weight"
    147                 ]
    149 for name, scorer in self._scorers.items():

AttributeError: 'function' object has no attribute '_accept_sample_weight'
```

### Versions

```shell
The `***` below is to obscure some personal details.


System:
    python: 3.11.13 | packaged by conda-forge | (main, Jun  4 2025, 14:52:34) [Clang 18.1.8 ]
executable: /Users/***/anaconda3/envs/***/bin/python3.11
   machine: macOS-15.5-arm64-arm-64bit

Python dependencies:
      sklearn: 1.7.0
          pip: 25.1.1
   setuptools: 80.9.0
        numpy: 2.2.6
        scipy: 1.15.2
       Cython: None
       pandas: 2.3.0
   matplotlib: None
       joblib: 1.5.1
threadpoolctl: 3.6.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 14
         prefix: libopenblas
       filepath: /Users/***/anaconda3/envs/***/lib/libopenblas.0.dylib
        version: 0.3.29
threading_layer: openmp
   architecture: VORTEX

       user_api: openmp
   internal_api: openmp
    num_threads: 14
         prefix: libomp
       filepath: /Users/***/anaconda3/envs/***/lib/libomp.dylib
        version: None
```

COMMENT:
First thing, this issue is only there if you don't enable metadata routing, i.e. this script works:

```py
import numpy as np
from sklearn.metrics import make_scorer, mean_squared_error
from sklearn.linear_model import Ridge
from sklearn.model_selection import GridSearchCV
import sklearn

sklearn.set_config(enable_metadata_routing=True)

def score_func(estimator, X, y, sample_weight=None, **kws):
    print(f"sample_weight is None? {sample_weight is None}")
    return 1


scorers = {
    "mse": make_scorer(mean_squared_error, greater_is_better=False).set_score_request(
        sample_weight=True
    ),
    "default": score_func,
}

rng = np.random.RandomState(0)
X = rng.rand(10, 2)
y = rng.rand(10)
sample_weight = rng.rand(10)

gs = GridSearchCV(
    Ridge().set_fit_request(sample_weight=True),
    scoring=scorers,
    param_grid={"alpha": [0.1, 1, 10]},
    refit=False,
)
gs.fit(X, y, sample_weight=sample_weight)
```

However, as you can see running the script, `score_func` does NOT get `sample_weight`, since it does not implement a correct `get_metadata_routing()` method. #30859 fixes some issues related to scorers surprisingly not raising when `sample_weight` is not provided though.

As for this issue, when metadata routing is NOT enabled, I would have liked `check_scoring` to handle all cases, and return something we know, as in a `_BaseScorer` of sorts. `_MultimetricScorer` should also run `check_scoring` on all its children, which at the moment it doesn't.

That cleans up quite a few places where we have repeated code and places where we accept `scoring` as a constructor arg, but the issue here is that we have defined a `scorer` in our API as a callable with `(estimator, X, y, ...)` signature, which isn't really true anymore, since a simple function with that signature, does not know how to handle metadata. So ideally, the only way to create a scorer should be a `make_scorer(func, ...)` where `func` is of signature `(y_pred, y_true, ...)`, and `make_scorer` handles creating the right class with all required methods.

Labels: Bug, module:metrics, Needs Investigation