I'm using IPython.
I declared a simple class MyClass(object)
, and in the console, when using the name MyClass, after the dot
operator, i hit Tab
.
One of the first suggestions i got was mro
, meaning MyClass.mro
. I hit enter, and the output i get is:
> <function mro>
Now i didn't define this method, and of course it returns the method resolution order of my class.
This method doesn't appear in the list returned by dir(MyClass)
, and so here comes my question:
How would I find any other such hidden features of classes or other objects?
The dir()
does not try to provide a complete output, just a reasonable approximation that is useful in the interactive interpreter.
The reason for dir
to not include __mro__
and mro
in the output can be found in the source code, under Objects/object.c
at line 1812:
/* Helper for PyObject_Dir of type objects: returns __dict__ and __bases__.
We deliberately don't suck up its __class__, as methods belonging to the
metaclass would probably be more confusing than helpful.
*/
static PyObject *
_specialized_dir_type(PyObject *obj)
And turns out that the mro
method and the __mro__
attribute are actually attributes of the metaclass, i.e. of type
:
>>> '__mro__' in object.__dict__
False
>>> '__mro__' in type.__dict__
True
>>> 'mro' in object.__dict__
False
>>> 'mro' in type.__dict__
True
Hence they are not shown in the output of dir
. Whether this is sensible or not depends. I believe most of the time you really do not want to see what the metaclass defines, since they are internals of the metaclass.
As explained in the documentation for dir() you can customize its output defining a __dir__
method. However this applies to the instances of the class:
class A(object):
def __dir__(self):
return ['a', 'b', 'c']
print(dir(A()), dir(A))
Output:
(['a', 'b', 'c'], ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'])
If you want to customize also the output of dir(A)
you have to use a custom metaclass:
class MyMeta(type):
def __dir__(self):
return ['a', 'b', 'c']
class A(object, metaclass=MyMeta):
# __metaclass__ = MyMeta # in python 2
def __dir__(self):
return ['a', 'b', 'c', 'd']
print(dir(A()), dir(A))
Output:
(['a', 'b', 'c', 'd'], ['a', 'b', 'c'])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With