diff --git a/numpydoc/docscrape_sphinx.py b/numpydoc/docscrape_sphinx.py
index d8a495e..a555ed0 100644
--- a/numpydoc/docscrape_sphinx.py
+++ b/numpydoc/docscrape_sphinx.py
@@ -79,21 +79,136 @@ class SphinxDocString(NumpyDocString):
                 out += ['']
         return out
 
-    def _str_param_list(self, name):
+    def _process_param(self, param, desc, autosum):
+        """Determine how to display a parameter
+
+        Emulates autosummary behavior if autosum is not None.
+
+        Parameters
+        ----------
+        param : str
+            The name of the parameter
+        desc : list of str
+            The parameter description as given in the docstring. This is
+            ignored when autosummary logic applies.
+        autosum : list or None
+            If a list, autosummary-style behaviour will apply for params
+            that are attributes of the class and have a docstring.
+            Names for autosummary generation will be appended to this list.
+
+            If None, autosummary is disabled.
+
+        Returns
+        -------
+        display_param : str
+            The marked up parameter name for display. This may include a link
+            to the corresponding attribute's own documentation.
+        desc : list of str
+            A list of description lines. This may be identical to the input
+            ``desc``, if ``autosum is None`` or ``param`` is not a class
+            attribute, or it will be a summary of the class attribute's
+            docstring.
+
+        Notes
+        -----
+        This does not have the autosummary functionality to display a method's
+        signature, and hence is not used to format methods.  It may be
+        complicated to incorporate autosummary's signature mangling, as it
+        relies on Sphinx's plugin mechanism.
+        """
+        param = param.strip()
+        display_param = '**%s**' % param
+
+        if autosum is None:
+            return display_param, desc
+
+        param_obj = getattr(self._obj, param, None)
+        if not (callable(param_obj)
+                or isinstance(param_obj, property)
+                or inspect.isgetsetdescriptor(param_obj)):
+            param_obj = None
+        obj_doc = pydoc.getdoc(param_obj)
+
+        if not (param_obj and obj_doc):
+            return display_param, desc
+
+        prefix = getattr(self, '_name', '')
+        if prefix:
+            autosum_prefix = '~%s.' % prefix
+            link_prefix = '%s.' % prefix
+        else:
+            autosum_prefix = ''
+            link_prefix = ''
+
+        # Referenced object has a docstring
+        autosum.append("    %s%s" % (autosum_prefix, param))
+        display_param = ':obj:`%s <%s%s>`' % (param,
+                                              link_prefix,
+                                              param)
+        if obj_doc:
+            # Overwrite desc. Take summary logic of autosummary
+            desc = re.split('\n\s*\n', obj_doc.strip(), 1)[0]
+            # XXX: Should this have DOTALL?
+            #      It does not in autosummary
+            m = re.search(r"^([A-Z].*?\.)(?:\s|$)",
+                          ' '.join(desc.split()))
+            if m:
+                desc = m.group(1).strip()
+            else:
+                desc = desc.partition('\n')[0]
+            desc = desc.split('\n')
+        return display_param, desc
+
+    def _str_param_list(self, name, fake_autosummary=False):
+        """Generate RST for a listing of parameters or similar
+
+        Parameter names are displayed as bold text, and descriptions
+        are in blockquotes.  Descriptions may therefore contain block
+        markup as well.
+
+        Parameters
+        ----------
+        name : str
+            Section name (e.g. Parameters)
+        fake_autosummary : bool
+            When True, the parameter names may correspond to attributes of the
+            object beign documented, usually ``property`` instances on a class.
+            In this case, names will be linked to fuller descriptions.
+
+        Returns
+        -------
+        rst : list of str
+        """
         out = []
         if self[name]:
+            if fake_autosummary:
+                autosum = []
+            else:
+                autosum = None
+
             out += self._str_field_list(name)
             out += ['']
             for param, param_type, desc in self[name]:
+                display_param, desc = self._process_param(param, desc, autosum)
+
                 if param_type:
-                    out += self._str_indent(['**%s** : %s' % (param.strip(),
-                                                              param_type)])
+                    out += self._str_indent(['%s : %s' % (display_param,
+                                                          param_type)])
                 else:
-                    out += self._str_indent(['**%s**' % param.strip()])
+                    out += self._str_indent([display_param])
                 if desc:
-                    out += ['']
+                    out += ['']  # produces a blockquote, rather than a dt/dd
                     out += self._str_indent(desc, 8)
                 out += ['']
+
+            if fake_autosummary and autosum:
+                if self.class_members_toctree:
+                    autosum.insert(0, '    :toctree:')
+                autosum.insert(0, '.. autosummary::')
+                out += ['..', '    HACK to make autogen generate docs:']
+                out += self._str_indent(autosum, 4)
+                out += ['']
+
         return out
 
     @property
@@ -130,7 +245,7 @@ class SphinxDocString(NumpyDocString):
                         or inspect.isgetsetdescriptor(param_obj)):
                     param_obj = None
 
-                if param_obj and (pydoc.getdoc(param_obj) or not desc):
+                if param_obj and pydoc.getdoc(param_obj):
                     # Referenced object has a docstring
                     autosum += ["   %s%s" % (prefix, param)]
                 else:
@@ -250,7 +365,8 @@ class SphinxDocString(NumpyDocString):
             'notes': self._str_section('Notes'),
             'references': self._str_references(),
             'examples': self._str_examples(),
-            'attributes': self._str_member_list('Attributes'),
+            'attributes': self._str_param_list('Attributes',
+                                               fake_autosummary=True),
             'methods': self._str_member_list('Methods'),
         }
         ns = dict((k, '\n'.join(v)) for k, v in ns.items())

Need Attributes displayable like param list
I've not investigated when/whether there was a change in numpydoc, but scikit-learn has long relied on Attributes (as per docstring, rather than than descriptors on the class) being listed like Parameters. See old docs at http://scikit-learn.org/0.18/modules/generated/sklearn.linear_model.LogisticRegression.html for instance.

We've merged a recent numpydoc into scikit-learn master, which uses `_str_member_list` to render Attributes, rather than `_str_param_list`. See new docs at http://scikit-learn.org/dev/modules/generated/sklearn.linear_model.LogisticRegression.html. The listing looks more like methods, and hence like what you get out of autosummary for descriptors, but it altogether (and particularly the type spec) looks wrong. I'm not sure how those type specs work well for any users of Attributes.

To fix scikit-learn's needs, I propose that we extend the Jinja templating of numpy_docstring.rst such that instead of just rendering strings with e.g. `{{ attributes }}`, we have Jinja statements like:

```
{% members_list Attributes %}
```
or perhaps Jinja filters like:
```
{% raw_attributes | members_list %}
```
but unless we want to compose filters, I'm not sure the benefit of this.

Would this be acceptable?
diff --git a/numpydoc/tests/test_docscrape.py b/numpydoc/tests/test_docscrape.py
index 297a0ac..2ae51c6 100644
--- a/numpydoc/tests/test_docscrape.py
+++ b/numpydoc/tests/test_docscrape.py
@@ -17,6 +17,8 @@ from numpydoc.docscrape_sphinx import (SphinxDocString, SphinxClassDoc,
 from nose.tools import (assert_equal, assert_raises, assert_list_equal,
                         assert_true)
 
+assert_list_equal.__self__.maxDiff = None
+
 if sys.version_info[0] >= 3:
     sixu = lambda s: s
 else:
@@ -897,8 +899,17 @@ class_doc_txt = """
         Current time.
     y : ndarray
         Current variable values.
-    x : float
-        Some parameter
+
+        * hello
+        * world
+    an_attribute : float
+        The docstring is printed instead
+    no_docstring : str
+        But a description
+    no_docstring2 : str
+    multiline_sentence
+    midword_period
+    no_period
 
     Methods
     -------
@@ -934,8 +945,17 @@ def test_class_members_doc():
         Current time.
     y : ndarray
         Current variable values.
-    x : float
-        Some parameter
+
+        * hello
+        * world
+    an_attribute : float
+        The docstring is printed instead
+    no_docstring : str
+        But a description
+    no_docstring2 : str
+    multiline_sentence
+    midword_period
+    no_period
 
     Methods
     -------
@@ -952,10 +972,38 @@ def test_class_members_doc():
 def test_class_members_doc_sphinx():
     class Foo:
         @property
-        def x(self):
+        def an_attribute(self):
             """Test attribute"""
             return None
 
+        @property
+        def no_docstring(self):
+            return None
+
+        @property
+        def no_docstring2(self):
+            return None
+
+        @property
+        def multiline_sentence(self):
+            """This is a
+            sentence. It spans multiple lines."""
+            return None
+
+        @property
+        def midword_period(self):
+            """The sentence for numpy.org."""
+            return None
+
+        @property
+        def no_period(self):
+            """This does not have a period
+            so we truncate its summary to the first linebreak
+
+            Apparently.
+            """
+            return None
+
     doc = SphinxClassDoc(Foo, class_doc_txt)
     non_blank_line_by_line_compare(str(doc),
     """
@@ -975,17 +1023,36 @@ def test_class_members_doc_sphinx():
 
     For usage examples, see `ode`.
 
-    .. rubric:: Attributes
-
-    .. autosummary::
-       :toctree:
-
-       x
-
-    =====  ==========
-    **t**  (float) Current time.
-    **y**  (ndarray) Current variable values.
-    =====  ==========
+    :Attributes:
+
+        **t** : float
+            Current time.
+        **y** : ndarray
+            Current variable values.
+
+            * hello
+            * world
+        :obj:`an_attribute <an_attribute>` : float
+            Test attribute
+        **no_docstring** : str
+            But a description
+        **no_docstring2** : str
+        :obj:`multiline_sentence <multiline_sentence>`
+            This is a sentence.
+        :obj:`midword_period <midword_period>`
+            The sentence for numpy.org.
+        :obj:`no_period <no_period>`
+            This does not have a period
+
+    ..
+        HACK to make autogen generate docs:
+        .. autosummary::
+            :toctree:
+
+            an_attribute
+            multiline_sentence
+            midword_period
+            no_period
 
     .. rubric:: Methods
 

pip install -e .
parse_log_pytest
sphinx>=1.2.3 Jinja2>=2.3
nose pytest
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster @ file:///croot/alabaster_1718201490751/work
babel @ file:///croot/babel_1737454360933/work
Brotli @ file:///croot/brotli-split_1736182456865/work
certifi @ file:///croot/certifi_1738623731865/work/certifi
charset-normalizer @ file:///croot/charset-normalizer_1721748349566/work
docutils @ file:///opt/conda/conda-bld/docutils_1657175430858/work
exceptiongroup==1.2.2
idna @ file:///croot/idna_1714398848350/work
imagesize @ file:///opt/conda/conda-bld/imagesize_1657179498843/work
importlib_metadata @ file:///croot/importlib_metadata-suite_1732633488278/work
iniconfig==2.1.0
Jinja2 @ file:///croot/jinja2_1741710844255/work
MarkupSafe @ file:///croot/markupsafe_1738584038848/work
nose==1.3.7
-e git+https://github.com/numpy/numpydoc.git@057ef572dd5ea547af2832e1b68d934cf953eafe#egg=numpydoc
packaging @ file:///croot/packaging_1734472117206/work
pluggy==1.5.0
Pygments @ file:///croot/pygments_1684279966437/work
PySocks @ file:///tmp/build/80754af9/pysocks_1605305812635/work
pytest==8.3.5
requests @ file:///croot/requests_1730999120400/work
snowballstemmer @ file:///tmp/build/80754af9/snowballstemmer_1637937080595/work
Sphinx @ file:///croot/sphinx_1718275386998/work
sphinxcontrib-applehelp @ file:///home/ktietz/src/ci/sphinxcontrib-applehelp_1611920841464/work
sphinxcontrib-devhelp @ file:///home/ktietz/src/ci/sphinxcontrib-devhelp_1611920923094/work
sphinxcontrib-htmlhelp @ file:///tmp/build/80754af9/sphinxcontrib-htmlhelp_1623945626792/work
sphinxcontrib-jsmath @ file:///home/ktietz/src/ci/sphinxcontrib-jsmath_1611920942228/work
sphinxcontrib-qthelp @ file:///home/ktietz/src/ci/sphinxcontrib-qthelp_1611921055322/work
sphinxcontrib-serializinghtml @ file:///croot/sphinxcontrib-serializinghtml_1718201486943/work
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
urllib3 @ file:///croot/urllib3_1737133630106/work
zipp @ file:///croot/zipp_1732630741423/work

name: numpydoc
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - alabaster=0.7.16=py39h06a4308_0
  - babel=2.16.0=py39h06a4308_0
  - brotli-python=1.0.9=py39h6a678d5_9
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2025.1.31=py39h06a4308_0
  - charset-normalizer=3.3.2=pyhd3eb1b0_0
  - docutils=0.18.1=py39h06a4308_3
  - idna=3.7=py39h06a4308_0
  - imagesize=1.4.1=py39h06a4308_0
  - importlib-metadata=8.5.0=py39h06a4308_0
  - jinja2=3.1.6=py39h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - markupsafe=3.0.2=py39h5eee18b_0
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pygments=2.15.1=py39h06a4308_1
  - pysocks=1.7.1=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - requests=2.32.3=py39h06a4308_1
  - setuptools=75.8.0=py39h06a4308_0
  - snowballstemmer=2.2.0=pyhd3eb1b0_0
  - sphinx=7.3.7=py39h5eee18b_0
  - sphinxcontrib-applehelp=1.0.2=pyhd3eb1b0_0
  - sphinxcontrib-devhelp=1.0.2=pyhd3eb1b0_0
  - sphinxcontrib-htmlhelp=2.0.0=pyhd3eb1b0_0
  - sphinxcontrib-jsmath=1.0.1=pyhd3eb1b0_0
  - sphinxcontrib-qthelp=1.0.3=pyhd3eb1b0_0
  - sphinxcontrib-serializinghtml=1.1.10=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - urllib3=2.3.0=py39h06a4308_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.21.0=py39h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - exceptiongroup==1.2.2
      - iniconfig==2.1.0
      - nose==1.3.7
      - pluggy==1.5.0
      - pytest==8.3.5
prefix: /opt/conda/envs/numpydoc

numpydoc/tests/test_docscrape.py::test_class_members_doc_sphinx
numpydoc/tests/test_docscrape.py::test_signature numpydoc/tests/test_docscrape.py::test_summary numpydoc/tests/test_docscrape.py::test_extended_summary numpydoc/tests/test_docscrape.py::test_parameters numpydoc/tests/test_docscrape.py::test_other_parameters numpydoc/tests/test_docscrape.py::test_returns numpydoc/tests/test_docscrape.py::test_yields numpydoc/tests/test_docscrape.py::test_returnyield numpydoc/tests/test_docscrape.py::test_section_twice numpydoc/tests/test_docscrape.py::test_notes numpydoc/tests/test_docscrape.py::test_references numpydoc/tests/test_docscrape.py::test_examples numpydoc/tests/test_docscrape.py::test_index numpydoc/tests/test_docscrape.py::test_str numpydoc/tests/test_docscrape.py::test_yield_str numpydoc/tests/test_docscrape.py::test_sphinx_str numpydoc/tests/test_docscrape.py::test_sphinx_yields_str numpydoc/tests/test_docscrape.py::test_parameters_without_extended_description numpydoc/tests/test_docscrape.py::test_escape_stars numpydoc/tests/test_docscrape.py::test_empty_extended_summary numpydoc/tests/test_docscrape.py::test_raises numpydoc/tests/test_docscrape.py::test_warns numpydoc/tests/test_docscrape.py::test_see_also numpydoc/tests/test_docscrape.py::test_see_also_parse_error numpydoc/tests/test_docscrape.py::test_see_also_print numpydoc/tests/test_docscrape.py::test_empty_first_line numpydoc/tests/test_docscrape.py::test_no_summary numpydoc/tests/test_docscrape.py::test_unicode numpydoc/tests/test_docscrape.py::test_plot_examples numpydoc/tests/test_docscrape.py::test_class_members numpydoc/tests/test_docscrape.py::test_duplicate_signature numpydoc/tests/test_docscrape.py::test_class_members_doc numpydoc/tests/test_docscrape.py::test_templated_sections
numpydoc/docscrape_sphinx.py
numpydoc/docscrape_sphinx.py