Official docs says:
If the object has a method named
__dir__(), this method will be called
and must return the list of attributes. This allows objects that
implement a custom__getattr__()or__getattribute__()function to
customize the waydir()reports their attributes.
If custom __dir__ implemented, results, returning by another function, inspect.getmembers(), also affected.
For example:
class С(object):
__slots__ = ['atr']
def __dir__(self):
return ['nothing']
def method(self):
pass
def __init__(self):
self.atr = 'string'
c = C()
print dir(f) #If we try this - well get ['nothing'] returned by custom __dir__()
print inspect.getmembers(f) #Here we get []
print f.__dict__ #And here - exception will be raised because of __slots__
How in this case list of names of object might be getted?
Answer to original question- does
inspect.getmembers()use__dir__()likedir()does?Here’s the source code for
inspect.getmembers()so we can see what it’s really doing:From this we see that it is using
dir()and just filtering the results a bit.How to get attributes with an overridden
__dir__()?According to this answer, it isn’t possible to always get a complete list of attributes, but we can still definitely get them in some cases/get enough to be useful.
From the docs:
So if you are not using
__slots__, you could look at your object’s__dict__(and it’s type object’s) to get basically the same info thatdir()would normally give you. So, just like withdir(), you would have to use a more rigorous method to get metaclass methods.If you are using
__slots__, then getting class attributes is, in a way, a bit more simple. Yes, there’s no dict, but there is__slots__itself, which contains the names of all of the attributes. For example, addingprint c.__slots__to your example code yields['atr']. (Again, a more rigorous approach is needed to get the attributes of superclasses as well.)How to get methods
You might need a different solution depending on the use case, but if you just want to find out the methods easily, you can simply use the builtin
help().Modified PyPy
dir()Here’s an alternative to some of the above: To get a version of
dir()that ignores user-defined__dir__methods, you could just take PyPy’s implementation ofdir()and delete the parts that reference__dir__methods.