Functions related to classes

introspection.iter_subclasses(cls, include_abstract=False)

Yields subclasses of the given class.

New in version 1.5.

Parameters
  • cls (type) – A base class

  • include_abstract (bool, default: False) – Whether abstract base classes should be included

Return type

Iterator[type]

Returns

An iterator yielding subclasses

introspection.get_subclasses(*args, **kwargs)

Collects all subclasses of the given class.

Parameters
  • cls – A base class

  • include_abstract – Whether abstract base classes should be included

Return type

Set[type]

Returns

A set of all subclasses

introspection.get_attributes(obj, include_weakref=False)

Returns a dictionary of all of obj’s attributes. This includes attributes stored in the object’s __dict__ as well as in __slots__.

Parameters
  • obj (Any) – The object whose attributes will be returned

  • include_weakref (bool, default: False) – Whether the value of the __weakref__ slot should be included in the result

Return type

Dict[str, Any]

Returns

A dict of {attr_name: attr_value}

introspection.get_abstract_method_names(cls)

Returns a set of names of abstract methods (and other things) in the given class. See also is_abstract().

New in version 1.4.

Parameters

cls (type) – A class

Return type

Set[str]

Returns

The names of all abstract methods in that class

introspection.safe_is_subclass(subclass, superclass)

A clone of issubclass() that returns False instead of throwing a TypeError.

New in version 1.2.

Parameters
  • subclass – The subclass

  • superclass – The superclass

Return type

bool

Returns

Whether subclass is a subclass of superclass

introspection.iter_slots(cls)

Iterates over all __slots__ of the given class, yielding (slot_name, slot_descriptor) tuples.

If a slot name is used more than once, all of them will be yielded in the order they appear in the class’s MRO.

Note that this function relies on the class-level __slots__ attribute - deleting or altering this attribute in any way may yield incorrect results.

Parameters

cls (type) – The class whose slots to yield

Return type

Iterator[Tuple[str, Any]]

Returns

An iterator yielding (slot_name, slot_descriptor) tuples

introspection.get_slot_names(cls)

Collects all of the given class’s __slots__, returning a set of slot names.

Parameters

cls (type) – The class whose slots to collect

Return type

Set[str]

Returns

A set containing the names of all slots

introspection.get_slot_counts(cls)

Collects all of the given class’s __slots__, returning a dict of the form {slot_name: count}.

Parameters

cls (type) – The class whose slots to collect

Return type

Dict[str, int]

Returns

A collections.Counter counting the number of occurrences of each slot

introspection.get_slots(cls)

Collects all of the given class’s __slots__, returning a dict of the form {slot_name: slot_descriptor}.

If a slot name is used more than once, only the descriptor that shadows all other descriptors of the same name is returned.

Parameters

cls (type) – The class whose slots to collect

Return type

Dict[str, Any]

Returns

A dict mapping slot names to descriptors

introspection.get_implicit_method_type(method_name)

Given the name of a method as input, returns what kind of method python automatically converts it to. The return value can be staticmethod, classmethod, or None.

Examples:

>>> get_implicit_method_type('frobnicate_quadrizzles')
>>> get_implicit_method_type('__new__')
<class 'staticmethod'>
>>> get_implicit_method_type('__init_subclass__')
<class 'classmethod'>

New in version 1.3.

Parameters

method_name (str) – The name of a dundermethod

Return type

Literal[None, <class ‘classmethod’>, <class ‘staticmethod’>]

Returns

The type of that method

introspection.fit_to_class(thing, cls, name=None)

Updates thing‘s metadata to match cls‘s.

thing can be one of the following:

If name is not None, thing will be renamed accordingly.

New in version 1.4.

Parameters
  • thing – The thing whose metadata should be updated

  • cls (type) – The class to copy the metadata from

  • name (Optional[str], default: None) – The name to rename thing to

introspection.add_method_to_class(method, cls, name=None, method_type=auto)

Adds method to cls‘s namespace under the given name.

If name is None, it defaults to method.__name__.

The method’s metadata (__name__, __qualname__, and __module__) will be updated to match the class.

If a method_type is passed in, it should have a value of staticmethod, classmethod, or None. If omitted, it is automatically determined by calling get_implicit_method_type(). The method is then automatically wrapped with the appropriate descriptor.

New in version 1.3.

Parameters
  • method – The method to add to the class

  • cls (type) – The class to which to add the method

  • name (Optional[str], default: None) – The name under which the method is registered in the class namespace

  • method_type – One of staticmethod, classmethod, or None (or omitted)

Return type

None

introspection.wrap_method(method, cls, name=None, method_type=auto)

Adds method to cls‘s namespace under the given name, wrapping the existing method (if one exists).

The replaced method will be passed in as the first positional argument (even before the implicit self). If the class previously didn’t implement this method, an appropriate dummy method will be passed in instead, which merely sends the call further up the MRO.

method_type has the same meaning as it does in add_method_to_class().

Example:

class Foo:
    def __init__(self, foo):
        self.foo = foo

    def __repr__(self):
        return f'<Foo object with foo={self.foo}>'

def custom_init(original_init, self, *args, **kwargs):
    original_init(self, *args, **kwargs)
    print('Initialized instance:', self)

wrap_method(custom_init, Foo, '__init__')

Foo(5)  # prints "Initialized instance: <Foo object with foo=5>"

Note

Adding a __new__ method to a class can lead to unexpected problems because of the way object.__new__ works.

If a class doesn’t implement a __new__ method at all, object.__new__ silently discards any arguments it receives. But if a class does implement a custom __new__ method, passing arguments into object.__new__ will throw an exception:

class ThisWorks:
    def __init__(self, some_arg):
        pass

class ThisDoesntWork:
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, some_arg):
        pass

ThisWorks(5)  # works
ThisDoesntWork(5)  # throws TypeError: object.__new__() takes exactly one argument

This is why, when this function is used to add a __new__ method to a class that previously didn’t have one, it automatically generates a dummy __new__ that attempts to figure out whether it should forward its arguments to the base class’s __new__ method or not. This is why the following code will work just fine:

class ThisWorks:
    def __init__(self, some_arg):
        pass

def __new__(original_new, cls, *args, **kwargs):
    return original_new(cls, *args, **kwargs)

wrap_method(__new__, ThisWorks)

ThisWorks(5)  # works!

However, it is impossible to always correctly figure out if the arguments should be passed on or not. If there is another __new__ method that passes on its arguments, things will go wrong:

class Parent:
    def __init__(self, some_arg):
        pass

class Child(Parent):
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)

def __new__(original_new, cls, *args, **kwargs):
    return original_new(cls, *args, **kwargs)

wrap_method(__new__, Parent)

Parent(5)  # works!
Child(5)  # throws TypeError

In such a scenario, the method sees that Child.__new__ exists, and therefore it is Child.__new__‘s responsibility to handle the arguments correctly. It should consume all the arguments, but doesn’t, so an exception is raised.

As a workaround, you can mark Child.__new__ as a method that forwards its arguments. This is done by setting its _forwards_args attribute to True:

Child.__new__._forwards_args = True

Child(5)  # works!

New in version 1.3.

Parameters
  • method – The method to add to the class

  • cls – The class to which to add the method

  • name – The name under which the method is registered in the class namespace

  • method_type – One of staticmethod, classmethod, or None (or omitted)