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:
A simple solution should be straightforward where we override the `__dir__` method on all classes that have conditional attributes.

```python
def __dir__(self):
    original_dir = super().__dir__()
    return [attr for attr in original_dir if hasattr(self, attr)]
```

We may want to find ways to be smarter if anyone just uses `avaliable_if` in the class somehow, which is a bit more difficult.

Labels: Bug