From 6ef0f656da9a9e8ec2b0cd3002551e961cf176aa Mon Sep 17 00:00:00 2001 From: CHINMAY <89741289+Das-Chinmay@users.noreply.github.com> Date: Thu, 26 Mar 2026 21:42:31 -0700 Subject: [PATCH 01/10] gh-72088: clarify inspect.ismethod returns False for class-level access Accessing a method through the class returns a plain function, not a bound method, so ismethod() returns False in that case. Add a note and a cross-reference to the 'instance methods' section of the data model reference to explain this. --- Doc/library/inspect.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index ff893a4513926a..5b47d80de9c20b 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -425,6 +425,11 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Return ``True`` if the object is a bound method written in Python. + Note that accessing a method through the class (rather than an instance) + returns a plain :term:`function`, not a bound method, so :func:`ismethod` + will return ``False`` in that case. See :ref:`instance-methods` in the + language reference for details. + .. function:: ispackage(object) From cb78792a742eac39c5d7d1337363012833373178 Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 18 May 2026 10:55:06 -0700 Subject: [PATCH 02/10] gh-72088: clarify inspect.ismethod and isfunction usage with class-level access Update inspect docs to note the behavioral differences between inspecting instance methods via the class versus via an instance when checking whether an object is a function or a method. --- Doc/library/inspect.rst | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 5b47d80de9c20b..61c7bb352d7771 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -425,10 +425,12 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Return ``True`` if the object is a bound method written in Python. - Note that accessing a method through the class (rather than an instance) - returns a plain :term:`function`, not a bound method, so :func:`ismethod` - will return ``False`` in that case. See :ref:`instance-methods` in the - language reference for details. + .. note:: + + Accessing an instance method through the class (rather than an instance) + returns a plain :term:`function`, not a bound method, so :func:`ismethod` + will return ``False`` in that case. See :ref:`instance-methods` in the + language reference for details. .. function:: ispackage(object) @@ -443,6 +445,13 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Return ``True`` if the object is a Python function, which includes functions created by a :term:`lambda` expression. + .. note:: + + Accessing an instance method through the class (rather than an instance) + returns a plain :term:`function`, not a bound method, so :func:`isfunction` + will return ``True`` in that case. See :ref:`instance-methods` in the + language reference for details. + .. function:: isgeneratorfunction(object) @@ -456,6 +465,13 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partialmethod` now return ``True`` if the wrapped function is a Python generator function. + .. note:: + + Accessing an instance method through the class (rather than an instance) + returns a plain :term:`function`, not a bound method, so :func:`isgeneratorfunction` + will return ``True`` in that case. See :ref:`instance-methods` in the + language reference for details. + .. function:: isgenerator(object) Return ``True`` if the object is a generator. @@ -482,6 +498,13 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partialmethod` now return ``True`` if the wrapped function is a :term:`coroutine function`. + .. note:: + + Accessing an instance method through the class (rather than an instance) + returns a plain :term:`function`, not a bound method, so :func:`iscoroutinefunction` + will return ``True`` in that case. See :ref:`instance-methods` in the + language reference for details. + .. function:: markcoroutinefunction(func) @@ -552,6 +575,13 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partialmethod` now return ``True`` if the wrapped function is a :term:`asynchronous generator` function. + .. note:: + + Accessing an instance method through the class (rather than an instance) + returns a plain :term:`function`, not a bound method, so :func:`isasyncgenfunction` + will return ``True`` in that case. See :ref:`instance-methods` in the + language reference for details. + .. function:: isasyncgen(object) Return ``True`` if the object is an :term:`asynchronous generator iterator` From 91b96f5cc476942e8404683d3854646ec46d2193 Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 18 May 2026 11:22:23 -0700 Subject: [PATCH 03/10] gh-72088: include @staticmethod behavior in inspect notes --- Doc/library/inspect.rst | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 61c7bb352d7771..305cdd73d2f1aa 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -432,6 +432,8 @@ attributes (see :ref:`import-mod-attrs` for module attributes): will return ``False`` in that case. See :ref:`instance-methods` in the language reference for details. + For static methods (:deco:`staticmethod`), this will always return ``False``. + .. function:: ispackage(object) @@ -452,6 +454,8 @@ attributes (see :ref:`import-mod-attrs` for module attributes): will return ``True`` in that case. See :ref:`instance-methods` in the language reference for details. + For static methods (:deco:`staticmethod`), this will always return ``True``. + .. function:: isgeneratorfunction(object) @@ -469,8 +473,11 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Accessing an instance method through the class (rather than an instance) returns a plain :term:`function`, not a bound method, so :func:`isgeneratorfunction` - will return ``True`` in that case. See :ref:`instance-methods` in the - language reference for details. + will return ``True`` if it is a generator function. See :ref:`instance-methods` + in the language reference for details. + + For a static method (:deco:`staticmethod`), this will return ``True`` if it + is a generator function. .. function:: isgenerator(object) @@ -502,8 +509,11 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Accessing an instance method through the class (rather than an instance) returns a plain :term:`function`, not a bound method, so :func:`iscoroutinefunction` - will return ``True`` in that case. See :ref:`instance-methods` in the - language reference for details. + will return ``True`` if it is a coroutine function. See :ref:`instance-methods` + in the language reference for details. + + For a static method (:deco:`staticmethod`), this will return ``True`` if it + is a coroutine function. .. function:: markcoroutinefunction(func) From 9f54b194a2cedfa0ba90a0f983b076948cf8f9c0 Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 18 May 2026 11:26:30 -0700 Subject: [PATCH 04/10] gh-72088: include @staticmethod behavior in inspect.isasyncgenfunction notes --- Doc/library/inspect.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 35740a0923f53b..4504bf6107bcdf 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -588,8 +588,11 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Accessing an instance method through the class (rather than an instance) returns a plain :term:`function`, not a bound method, so :func:`isasyncgenfunction` - will return ``True`` in that case. See :ref:`instance-methods` in the - language reference for details. + will return ``True`` if it is an asynchronous generator function. See + :ref:`instance-methods` in the language reference for details. + + For a static method (:deco:`staticmethod`), this will return ``True`` if it + is an asynchronous generator function. .. function:: isasyncgen(object) From c533f7590a32eedfcb1049c8dec960fca55a3489 Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 18 May 2026 12:09:08 -0700 Subject: [PATCH 05/10] gh-72088: rework inspect docs checks after discussion --- Doc/library/inspect.rst | 39 +++++---------------------------------- 1 file changed, 5 insertions(+), 34 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 4504bf6107bcdf..30fe928f9d8620 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -431,8 +431,6 @@ attributes (see :ref:`import-mod-attrs` for module attributes): will return ``False`` in that case. See :ref:`instance-methods` in the language reference for details. - For static methods (:deco:`staticmethod`), this will always return ``False``. - .. function:: ispackage(object) @@ -449,17 +447,18 @@ attributes (see :ref:`import-mod-attrs` for module attributes): .. note:: Accessing an instance method through the class (rather than an instance) - returns a plain :term:`function`, not a bound method, so :func:`isfunction` - will return ``True`` in that case. See :ref:`instance-methods` in the + returns a bound method, not a :term:`function`, so :func:`isfunction` + will return ``False`` in that case. See :ref:`instance-methods` in the language reference for details. - For static methods (:deco:`staticmethod`), this will always return ``True``. - .. function:: isgeneratorfunction(object) Return ``True`` if the object is a Python generator function. + It also returns ``True`` for bound methods created from Python generator functions + (see :ref:`typesmethods` for more information). + .. versionchanged:: 3.8 Functions wrapped in :func:`functools.partial` now return ``True`` if the wrapped function is a Python generator function. @@ -468,15 +467,6 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partialmethod` now return ``True`` if the wrapped function is a Python generator function. - .. note:: - - Accessing an instance method through the class (rather than an instance) - returns a plain :term:`function`, not a bound method, so :func:`isgeneratorfunction` - will return ``True`` if it is a generator function. See :ref:`instance-methods` - in the language reference for details. - - For a static method (:deco:`staticmethod`), this will return ``True`` if it - is a generator function. .. function:: isgenerator(object) @@ -504,16 +494,6 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partialmethod` now return ``True`` if the wrapped function is a :term:`coroutine function`. - .. note:: - - Accessing an instance method through the class (rather than an instance) - returns a plain :term:`function`, not a bound method, so :func:`iscoroutinefunction` - will return ``True`` if it is a coroutine function. See :ref:`instance-methods` - in the language reference for details. - - For a static method (:deco:`staticmethod`), this will return ``True`` if it - is a coroutine function. - .. function:: markcoroutinefunction(func) @@ -584,15 +564,6 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partialmethod` now return ``True`` if the wrapped function is a :term:`asynchronous generator` function. - .. note:: - - Accessing an instance method through the class (rather than an instance) - returns a plain :term:`function`, not a bound method, so :func:`isasyncgenfunction` - will return ``True`` if it is an asynchronous generator function. See - :ref:`instance-methods` in the language reference for details. - - For a static method (:deco:`staticmethod`), this will return ``True`` if it - is an asynchronous generator function. .. function:: isasyncgen(object) From 31a05c62ba34a70f58c9dff052606786e576d9ec Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 18 May 2026 12:14:25 -0700 Subject: [PATCH 06/10] Fix phrasing and formatting --- Doc/library/inspect.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 30fe928f9d8620..dea661714a0a4b 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -446,7 +446,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes): .. note:: - Accessing an instance method through the class (rather than an instance) + Accessing an instance method through the instance (rather than the class) returns a bound method, not a :term:`function`, so :func:`isfunction` will return ``False`` in that case. See :ref:`instance-methods` in the language reference for details. @@ -467,7 +467,6 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partialmethod` now return ``True`` if the wrapped function is a Python generator function. - .. function:: isgenerator(object) Return ``True`` if the object is a generator. @@ -564,7 +563,6 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Functions wrapped in :func:`functools.partialmethod` now return ``True`` if the wrapped function is a :term:`asynchronous generator` function. - .. function:: isasyncgen(object) Return ``True`` if the object is an :term:`asynchronous generator iterator` From bd3d3cf8771a0c44d3ffcc2e9cc26a4664bcf992 Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 18 May 2026 17:24:27 -0400 Subject: [PATCH 07/10] Apply suggestions from code pair Co-authored-by: Petr Viktorin --- Doc/library/inspect.rst | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index dea661714a0a4b..f094b12cea925b 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -426,10 +426,38 @@ attributes (see :ref:`import-mod-attrs` for module attributes): .. note:: - Accessing an instance method through the class (rather than an instance) - returns a plain :term:`function`, not a bound method, so :func:`ismethod` - will return ``False`` in that case. See :ref:`instance-methods` in the - language reference for details. + For example, given this class:: + + >>> class Class: + ... def say_hello(self): + ... print('hello!') + >>> + + A bound method (also known as an *instance method*) is created when + accessing ``say_hello`` (a :term:`function` defined in a + class namespace) through an instance of the class:: + + >>> instance = Class() + + >>> instance.say_hello + > + >>> ismethod(instance.say_hello) + True + >>> isfunction(instance.say_hello) + False + + Accessing ``say_hello`` through the class will return the function itself. + For this function, :func:`ismethod` will return ``False``, + but :func:`isfunction` will return ``True``:: + + >>> Class.say_hello + + >>> ismethod(Class.say_hello) + False + >>> isfunction(Class.say_hello) + True + + See :ref:`typesmethods` for details. .. function:: ispackage(object) From 4d500ea4628fd505882cf0dd842caa6b7c155a73 Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 18 May 2026 14:26:44 -0700 Subject: [PATCH 08/10] Move isfunction next to ismethod --- Doc/library/inspect.rst | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index f094b12cea925b..4a3ced8097f4d5 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -460,24 +460,19 @@ attributes (see :ref:`import-mod-attrs` for module attributes): See :ref:`typesmethods` for details. -.. function:: ispackage(object) - - Return ``True`` if the object is a :term:`package`. - - .. versionadded:: 3.14 - - .. function:: isfunction(object) Return ``True`` if the object is a Python function, which includes functions created by a :term:`lambda` expression. - .. note:: + See the note for :func:`~inspect.ismethod` for an example. + + +.. function:: ispackage(object) - Accessing an instance method through the instance (rather than the class) - returns a bound method, not a :term:`function`, so :func:`isfunction` - will return ``False`` in that case. See :ref:`instance-methods` in the - language reference for details. + Return ``True`` if the object is a :term:`package`. + + .. versionadded:: 3.14 .. function:: isgeneratorfunction(object) From ab0049ff1e930a9c24532935ec2b08d0f3008e3f Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 18 May 2026 14:28:39 -0700 Subject: [PATCH 09/10] Fix whitespace --- Doc/library/inspect.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 4a3ced8097f4d5..3ba4fe76713704 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -427,7 +427,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes): .. note:: For example, given this class:: - + >>> class Class: ... def say_hello(self): ... print('hello!') From 7e0e9bf1fe9cdb90f2ca44aadf0def663fa652f5 Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 18 May 2026 14:36:33 -0700 Subject: [PATCH 10/10] Use more descriptive class name for readability and fix indent --- Doc/library/inspect.rst | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 3ba4fe76713704..92840e702fbbfe 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -428,33 +428,32 @@ attributes (see :ref:`import-mod-attrs` for module attributes): For example, given this class:: - >>> class Class: - ... def say_hello(self): - ... print('hello!') - >>> + >>> class Greeter: + ... def say_hello(self): + ... print('hello!') A bound method (also known as an *instance method*) is created when - accessing ``say_hello`` (a :term:`function` defined in a - class namespace) through an instance of the class:: + accessing ``say_hello`` (a :term:`function` defined in the + ``Greeter`` namespace) through an instance of the ``Greeter`` class:: - >>> instance = Class() + >>> instance = Greeter() >>> instance.say_hello - > + > >>> ismethod(instance.say_hello) True >>> isfunction(instance.say_hello) False - Accessing ``say_hello`` through the class will return the function itself. - For this function, :func:`ismethod` will return ``False``, - but :func:`isfunction` will return ``True``:: + Accessing ``say_hello`` through the ``Greeter`` class will return the + function itself. For this function, :func:`ismethod` will return + ``False``, but :func:`isfunction` will return ``True``:: - >>> Class.say_hello - - >>> ismethod(Class.say_hello) + >>> Greeter.say_hello + + >>> ismethod(Greeter.say_hello) False - >>> isfunction(Class.say_hello) + >>> isfunction(Greeter.say_hello) True See :ref:`typesmethods` for details.