[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