Is there a way, given a simple Class, to output all the possible attributes for it? Standard attributes like __class__
and __doc__
and special read only attributes like __mro__
, __bases__
et al. Generally, all present attributes?
Considering the most simplistic case for a Class:
class myClass:
pass
The dir()
, vars()
and inspect.getmembers()
all exclude certain builtin
attributes. The most complete list is offered by using myClass.__dir__(MyClass)
which, while adding built in attributes, excludes user defined attributes of MyClass
, for example:
In [3]: set(MyClass.__dir__(MyClass)) - set(dir(MyClass))
Out[3]:
{'__abstractmethods__', '__base__', '__bases__',
'__basicsize__', '__call__', '__dictoffset__',
'__flags__', '__instancecheck__', '__itemsize__',
'__mro__', '__name__', '__prepare__', '__qualname__',
'__subclasscheck__', '__subclasses__', '__text_signature__',
'__weakrefoffset__', 'mro'}
According to one of the added similar questions, this is not possible. If presently still not possible, what is the rationale behind "hiding" certain attributes like __bases__
(from standard calls to dir(), vars() & inspect
and not ones like __name__
?
How to get a complete list of object's methods and attributes?
This is the most likely to be labeled as a duplicate, but, it is old and mostly regarding
Python 2.x
. The accepted answer is that there isn't a way but it was provided in 08'. The most recent answer in 12' suggestsdir()
for new style classes.
Print all properties of a Python Class
Similar title, different content.
Offers
dir()
andinspect
solutions.
Get all object attributes in Python?
Again, proposing
dir()
.
dir()
is basically a convenience method, it is not supposed to return everything, what it basically does is that it recursively returns everything found in the dictionary of a class and its bases.
PyPy's implementation of dir()
is quite easy to understand:
def dir(*args):
...
elif isinstance(obj, (types.TypeType, types.ClassType)):
# Don't look at __class__, as metaclass methods would be confusing.
return sorted(_classdir(obj))
...
def _classdir(klass):
"""Return a set of the accessible attributes of class/type klass.
This includes all attributes of klass and all of the base classes
recursively.
"""
names = set()
ns = getattr(klass, '__dict__', None)
if ns is not None:
names.update(ns)
bases = getattr(klass, '__bases__', None)
if bases is not None:
# Note that since we are only interested in the keys, the order
# we merge classes is unimportant
for base in bases:
names.update(_classdir(base))
return names
As each class basically inherits from object
you will see some dunder methods included because they are actually part of object
's dictionary:
>>> class A(object):
pass
...
>>> set(dir(A)) == set(list(object.__dict__) + list(A.__dict__))
True
Now what about
__bases__
and other missing items?
First of all object
itself is an instance of something, well it's bit of a mess actually:
>>> isinstance(type, object)
True
>>> isinstance(object, type)
True
>>> issubclass(type, object)
True
>>> issubclass(object, type)
False
>>> type.mro(object)
[<type 'object'>]
>>> type.mro(type)
[<type 'type'>, <type 'object'>]
So, all of the attributes like __bases__
, __ge__
etc are actually part of type
:
>>> list(type.__dict__)
['__module__', '__abstractmethods__', '__getattribute__', '__weakrefoffset__', '__dict__', '__lt__', '__init__', '__setattr__', '__subclasses__', '__new__', '__base__', '__mro__', 'mro', '__dictoffset__', '__call__', '__itemsize__', '__ne__', '__instancecheck__', '__subclasscheck__', '__gt__', '__name__', '__eq__', '__basicsize__', '__bases__', '__flags__', '__doc__', '__delattr__', '__le__', '__repr__', '__hash__', '__ge__']
Hence when we do A.__bases__
we are actually looking up a descriptor on type of A
, i.e type
:
>>> A.__bases__
(<type 'object'>,)
>>> type(A).__dict__['__bases__'].__get__(A, type)
(<type 'object'>,)
So, as A
is an instance of type
these methods are not part of its own dictionary but its type's dictionary.
>> class A(object):
... spam = 'eggs'
...
>>> a = A()
>>> a.foo = 100
>>> a.bar = 200
>>> a.__dict__
{'foo': 100, 'bar': 200}
>>> A.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'A' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None, 'spam': 'eggs'})
As, type
is a subclass of object
, the dir()
call on type
will contain some items from object
:
>>> set(dir(type)) - set(type.__dict__)
set(['__reduce_ex__', '__str__', '__format__', '__reduce__', '__class__', '__subclasshook__', '__sizeof__'])
__bases__
are just inherited from type
and so calling a function like dir()
on a subclass of type
just won't return the inherited attributes. Also, regarding the existence of a function that fetches everything, I'm guessing the short answer is that if I want a function like that, better implement it myself because it doesn't exist, right? — Oct 12, 2015 at 21:02 dir()
on a subclass of type" should be "dir()
on an instance of type
", for example if you create a metaclass that has some attributes then its instances(aka classes) won't have those attributes visible to us but the attribute access will still work. No, there's no such function available, at least not in standard library. — Oct 13, 2015 at 05:42 type
like __ ge__
are visible in __dict__
and or __dir__
and others like __bases__
are not. — Oct 13, 2015 at 07:22 __dict__
, and other properties like __bases__
are not: set(dir(A)) == set(list(object.__dict__) + list(A.__dict__))
. Python 2: ideone.com/TR0YPh ; Python 3: ideone.com/tmlHfW — Oct 13, 2015 at 08:51 External links referenced by this document:
Local articles referenced by this article: