Skip to content

Document that inspect.isclass returns False for GenericAlias instances #132467

Open

Description

@RobertoPrevato

Bug report

Bug description:

Hi
I am not sure if this is a bug, but I use the bug template because I couldn't find a better one to submit questions like this one.

The documentation says, "User-defined generic classes can be instantiated.".

import inspect
from typing import TypeVar, Generic

T = TypeVar("T")


class Node(Generic[T]):
    x: T  # Instance attribute (see below)

    def __init__(self, label: T | None = None) -> None:
        self.label = label


x = Node("")  # Inferred type is Node[str]
y = Node(0)  # Inferred type is Node[int]
z = Node()  # Inferred type is Node[Any]


# Also OK:
y = Node[int](0)


print(inspect.isclass(Node))  # True
print(inspect.isclass(Node[int]))  # False  (shouldn't this be True?)
print(inspect.isclass(Node[str]))  # False  (shouldn't this be True?)

In the example above, shouldn't calls such as inspect.isclass(Node[int]) return True, since they can be instantiated and used like normal classes?

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Linked PRs

Activity

  1. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Apr 13, 2025
  2. picnixz commented on Apr 13, 2025

    @picnixz
    Member

    I would regard Node[int] as the specialization of a generic class (similar to specialization of a C++ template class or Java/TypeScript generics), hence a class. The docs also say (emphasis mine):

    Note that the runtime type (class) of p and q is still just Node – Node[int] and Node[str] are distinguishable class objects, but the runtime class of the objects created by instantiating them doesn’t record the distinction.

    So according to this, inspect.isclass() should indeed return True. However, at runtime, Node[int] is a GenericAlias instance so should it still be considered a class? I don't have an answer to this question but I'd like to point that changing the behavior of inspect.isclass may cause downstream issues where one would not expect to filter GenericAlias objects.

    cc @JelleZijlstra

  3. changed the title [-]inspect.isclass returns False for user-defined Generics[/-] [+]inspect.isclass returns False for `GenericAlias` instances[/+] on Apr 13, 2025
  4. AlexWaygood commented on Apr 13, 2025

    @AlexWaygood
    Member

    The behaviour here is correct. You can see #89828, and its many linked sub-issues, for the various bugs that can be caused if GenericAlias instances are considered exactly equivalent to classes at runtime.

    I'd be open to making an improvement to the docs somewhere if the current docs are confusing, however!

  5. sobolevn commented on Apr 13, 2025

    @sobolevn
    Member

    I also agree that changing anything in inspect.is* can break a lot of code. And it is easier to adapt any checks in your own code: inspect.isclass(obj) or isinstance(obj, GenericAlias) - for example.

  6. picnixz commented on Apr 13, 2025

    @picnixz
    Member

    I think we should improve the docs by saying that GenericAlias instances are not considered to be classes by inspect.isclass, although they behave as a class.

    Note

    For newcomers, they should update both the online docs (rst) and the docstring. If possible (and if this is not already the case), they could also add a test for that.

  7. changed the title [-]inspect.isclass returns False for `GenericAlias` instances[/-] [+]Document that `inspect.isclass` returns False for `GenericAlias` instances[/+] on Apr 13, 2025
  8. removed
    stdlibStandard Library Python modules in the Lib/ directory
    on Apr 13, 2025
  9. added and removed
    type-bugAn unexpected behavior, bug, or error
    on Apr 13, 2025
  10. AbduazizZiyodov commented on Apr 13, 2025

    @AbduazizZiyodov
    Contributor

    @sobolevn Can you assign me to this issue ? I will work on it

  11. sobolevn commented on Apr 13, 2025

    @sobolevn
    Member

    @AbduazizZiyodov sure, please go ahead :)

  12. AbduazizZiyodov commented on May 3, 2025

    @AbduazizZiyodov
    Contributor

    @sobolevn: I also agree that changing anything in inspect.is* can break a lot of code. And it is easier to adapt any checks in your own code: inspect.isclass(obj) or isinstance(obj, GenericAlias) - for example.

    isinstance(Node[int], GenericAlias) is also returning False:

    # Definition of generic Node is same
    >>> inspect.isclass(Node[int])
    False # ok
    >>> from types import GenericAlias
    >>> inspect.isclass(Node[int]) or isinstance(Node[int], GenericAlias)
    False # ?
    >>> isinstance(Node[int], GenericAlias)
    False # ?

    Version: Python 3.14.0a7+, is that expected behaviour?

  13. AbduazizZiyodov commented on May 3, 2025

    @AbduazizZiyodov
    Contributor

    But this behaves as expected:

    >>> from typing import _GenericAlias as GenericAlias
    >>> isinstance(Node[int], GenericAlias)
    True

    I see that, there was discussion about types.GenericAlias VS typing._GenericAlias. As I understand this is documented in code, should we document in online docs ?

  14. AbduazizZiyodov commented on May 6, 2025

    @AbduazizZiyodov
    Contributor
  15. added 2 commits that reference this issue on Jun 3, 2026
  16. added a commit that references this issue on Jun 8, 2026
  17. added a commit that references this issue on Jun 9, 2026
  18. added a commit that references this issue on Jun 12, 2026
  19. added a commit that references this issue on Jun 17, 2026
  20. added a commit that references this issue on Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

docsDocumentation in the Doc direasy

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions