[Tutor] How to get all methods of "object"?

Eryk Sun eryksun at gmail.com
Sun Sep 22 02:05:23 EDT 2019


On 9/21/19, boB Stepp <robertvstepp at gmail.com> wrote:
>
> But I know at least one that is not listed:  __dict__  And I would not
> be surprised if there are others.

The base class `object` has a dict, but it's accessed via the
`__dict__` descriptor from the base metaclass, `type`. dir() does not
show metaclass attributes because that would be confusing when the
metaclass and class implement the same method.

Note that `object` itself doesn't provide its own `__dict__`
descriptor, since instances of `object` do not have a dict.

Builtin descriptor types in CPython happen to have 'descriptor' in
their name (i.e. wrapper_descriptor, method_descriptor,
classmethod_descriptor, getset_descriptor). Let's use this as a
shortcut to list descriptors that are provided by the base class
`object`, the base metaclass `type`, and an empty `SpamClass` that's
derived from `object`:

    >>> isdescr = lambda o: 'descriptor' in type(o).__name__
    >>> names = set(n for n,o in vars(type).items() if isdescr(o))
    >>> meta_names = set(n for n,o in vars(type).items() if isdescr(o))
    >>> sub_names = set(n for n,o in vars(SpamClass).items() if isdescr(o))

Here's what `object` and `type` provide in common:

    >>> print(*sorted(meta_names & names), sep='\n')
    __delattr__
    __dir__
    __getattribute__
    __init__
    __repr__
    __setattr__
    __sizeof__

This means that the above special methods are implemented separately
for classes. Note that the __dir__ method, which is called by builtin
`dir`, is special-cased for classes. Also note the absence of __new__
from this list. object.__new__ and type.__new__ are special cased as
pre-bound class methods:

    >>> object.__new__.__self__ is object
    True
    >>> type.__new__.__self__ is type
    True

If overridden in pure Python,  __new__ is added to a class dict as a
staticmethod, and for class instantiation it gets called implicitly
with the instantiated class as its first argument.

Moving on, here's what base `object` uniquely provides:

    >>> print(*sorted(names - meta_names), sep='\n')
    __class__
    __eq__
    __format__
    __ge__
    __gt__
    __hash__
    __init_subclass__
    __le__
    __lt__
    __ne__
    __reduce__
    __reduce_ex__
    __str__
    __subclasshook__

Notice the lack of __dict__. However, instances of most classes do
have a dict, so let's check what a subclass has that base `object`
does not have:

    >>> print(*sorted(sub_names - names), sep='\n')
    __dict__
    __weakref__

We can force instances of a class to not have either of these 'slots'
by defining __slots__ in the class without including them, e.g.
`__slots__ = ()`.

Finally, here's what `type` uniquely provides for its instances, i.e.
for classes:

    >>> print(*sorted(meta_names - names), sep='\n')
    __abstractmethods__
    __base__
    __bases__
    __basicsize__
    __call__
    __dict__
    __dictoffset__
    __doc__
    __flags__
    __instancecheck__
    __itemsize__
    __module__
    __mro__
    __name__
    __prepare__
    __qualname__
    __subclasscheck__
    __subclasses__
    __text_signature__
    __weakrefoffset__
    mro

Note that the following attributes are CPython extensions that are not
discussed in the docs:

    __abstractmethods__
    __base__
    __basicsize__
    __dictoffset__
    __flags__
    __itemsize__
    __text_signature__
    __weakrefoffset__

Removing these narrows the list down to the following documented attributes:

    __bases__
    __call__
    __dict__
    __doc__
    __instancecheck__
    __module__
    __mro__
    __name__
    __prepare__
    __qualname__
    __subclasscheck__
    __subclasses__
    mro

Refer to the docs for definitions and discussion of these attributes:

https://docs.python.org/3/reference/datamodel.html
https://docs.python.org/3/library/stdtypes.html
https://docs.python.org/3/library/abc.html
https://docs.python.org/3/library/pickle.html


More information about the Tutor mailing list