Inaccurate Attribute Listing with dir(obj) for Classes Using available_if Conditional Method Decorator

### Describe the bug

When utilizing the `available_if` decorator from SciKit Learn to conditionally expose methods based on specific object state or conditions, we observe that the `dir(obj)` function may return inaccurate results. Specifically, `dir(obj)` continues to list methods that should be conditionally hidden based on the `available_if` decorator's logic. This discrepancy arises because the `__dir__` method on the affected classes does not dynamically account for this conditional availability. As a result, users and consuming code may be misled about the actual methods available for use on instances of the class at runtime, potentially leading to unexpected `AttributeErrors` when accessing supposedly available methods.

### Steps/Code to Reproduce

I will test with the SVC, but it can apply to other classes.

```python
from sklearn.svm import SVC
from sklearn.datasets import load_iris

X, y = load_iris(return_X_y=True)

model = SVC(probability=False)
model.fit(X[:100], y[:100])

# Check if 'predict_proba' is listed by dir()
print("'predict_proba' in dir(model):", "predict_proba" in dir(model))

# Attempt to call 'predict_proba'
try:
    prob_predictions = model.predict_proba(X[:2])
    print("Predict_proba called successfully.")
except AttributeError as e:
    print("Attempting to call 'predict_proba' raised an AttributeError:", e)

```

### Expected Results

It should print out the following:
```
'predict_proba' in dir(model): False
Attempting to call 'predict_proba' raised an AttributeError: predict_proba is not available when probability=False
```

Methods decorated with `available_if` and whose conditions raise an `AttributeError` should not appear in the list returned by `dir(obj)`.

### Actual Results

It should print out the following:
```
'predict_proba' in dir(model): True
Attempting to call 'predict_proba' raised an AttributeError: predict_proba is not available when probability=False
```

Methods decorated with `available_if` and whose conditions raise an `AttributeError` appears in the list returned by `dir(obj)`.

Traceback when you show the error itself (comes from the check in `available_if`.
```
Traceback (most recent call last):
  File "/Users/kmcgrady/Projects/test-scripts/xg_example.py", line 48, in <module>
    prob_predictions = model.predict_proba(X[:2])
  File "/Users/kmcgrady/.local/share/virtualenvs/test-scripts-fLg6VU9n/lib/python3.10/site-packages/sklearn/utils/_available_if.py", line 31, in __get__
    if not self.check(obj):
  File "/Users/kmcgrady/.local/share/virtualenvs/test-scripts-fLg6VU9n/lib/python3.10/site-packages/sklearn/svm/_base.py", line 827, in _check_proba
    raise AttributeError(
AttributeError: predict_proba is not available when probability=False
```

### Versions

```shell
System:
    python: 3.10.10 (main, May 13 2023, 16:09:51) [Clang 14.0.3 (clang-1403.0.22.14.1)]
executable: /Users/kmcgrady/.local/share/virtualenvs/test-scripts-fLg6VU9n/bin/python
   machine: macOS-14.3.1-arm64-arm-64bit

Python dependencies:
      sklearn: 1.3.2
          pip: 23.3.1
   setuptools: 68.2.2
        numpy: 1.26.4
        scipy: 1.11.4
       Cython: None
       pandas: 2.2.1
   matplotlib: 3.8.2
       joblib: 1.3.2
threadpoolctl: 3.2.0

Built with OpenMP: True

threadpoolctl info:
       user_api: openmp
   internal_api: openmp
    num_threads: 10
         prefix: libomp
       filepath: /Users/kmcgrady/.local/share/virtualenvs/test-scripts-fLg6VU9n/lib/python3.10/site-packages/sklearn/.dylibs/libomp.dylib
        version: None

       user_api: blas
   internal_api: openblas
    num_threads: 10
         prefix: libopenblas
       filepath: /Users/kmcgrady/.local/share/virtualenvs/test-scripts-fLg6VU9n/lib/python3.10/site-packages/numpy/.dylibs/libopenblas64_.0.dylib
        version: 0.3.23.dev
threading_layer: pthreads
   architecture: armv8

       user_api: blas
   internal_api: openblas
    num_threads: 10
         prefix: libopenblas
       filepath: /Users/kmcgrady/.local/share/virtualenvs/test-scripts-fLg6VU9n/lib/python3.10/site-packages/scipy/.dylibs/libopenblas.0.dylib
        version: 0.3.21.dev
threading_layer: pthreads
   architecture: armv8
```

COMMENT:
I think it would be useful to fix this. Though I'd not be surprised if it got hairy real quick, doing magic like `available_if` tends to lead you down paths of "I never wanted to know this much about X".

Some cases that we should consider and make sure we don't make any of them worse (ideally we'd fix all of them but maybe we can't):
* `dir(est_instance)`
* `help(est_instance)`
* `dir(EstimatorClass)` - should list all methods
* tab-completion in something like IPython `est_instance.<tab>`
* the generated HTML API docs should continue to list the method (I think)

The proposed `__dir__` fixes all of them as far as I can tell, except `help(est)`. This still lists the "hidden" method.

edit: though I am not sure if it is really a bug for `help` to keep listing the method. It internally uses `pydoc` which, I think, lists all methods defined on the class

Labels: Bug