Functions related to classes¶
- introspection.iter_subclasses(cls, include_abstract=False)¶
Yields subclasses of the given class.
New in version 1.5.
- introspection.get_subclasses(*args, **kwargs)¶
Collects all subclasses of the given class.
- 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__.
- 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.
- introspection.safe_is_subclass(subclass, superclass)¶
A clone of
issubclass()that returnsFalseinstead of throwing aTypeError.New in version 1.2.
- Parameters
subclass – The subclass
superclass – The superclass
- Return type
- Returns
Whether
subclassis a subclass ofsuperclass
- 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.
- introspection.get_slot_names(cls)¶
Collects all of the given class’s
__slots__, returning a set of slot names.
- 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
- Returns
A
collections.Countercounting 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.
- 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, orNone.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.
- introspection.fit_to_class(thing, cls, name=None)¶
Updates
thing‘s metadata to matchcls‘s.thingcan be one of the following:A function
A
property
If
nameis notNone,thingwill be renamed accordingly.New in version 1.4.
- introspection.add_method_to_class(method, cls, name=None, method_type=auto)¶
Adds
methodtocls‘s namespace under the givenname.If
nameisNone, it defaults tomethod.__name__.The method’s metadata (
__name__,__qualname__, and__module__) will be updated to match the class.If a
method_typeis passed in, it should have a value ofstaticmethod,classmethod, orNone. If omitted, it is automatically determined by callingget_implicit_method_type(). The method is then automatically wrapped with the appropriate descriptor.New in version 1.3.
- introspection.wrap_method(method, cls, name=None, method_type=auto)¶
Adds
methodtocls‘s namespace under the givenname, 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_typehas the same meaning as it does inadd_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 wayobject.__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 intoobject.__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 isChild.__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_argsattribute toTrue: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, orNone(or omitted)