dir
does not list all attributes:
The docs say:
The resulting list is not necessarily complete...
The default dir() mechanism behaves differently with different types
of objects, as it attempts to produce the most relevant, rather than
complete, information...
Because dir() is supplied primarily as a convenience for use at an
interactive prompt, it tries to supply an interesting set of names
more than it tries to supply a rigorously or consistently defined set
of names, and its detailed behavior may change across releases. For
example, metaclass attributes are not in the result list when the
argument is a class.
Also, I assume that you tested '__eq__' in dir(thing)
-- note the quotation marks -- since dir
returns a list of strings.
ジョージ shows a way to list all attributes based on code from the rlcompleter module:
import rlcompleter
def get_object_attrs(obj):
"""
based on code from the rlcompleter module
See https://stackoverflow.com/a/10313703/190597 (ジョージ)
"""
ret = dir(obj)
## if "__builtins__" in ret:
## ret.remove("__builtins__")
if hasattr(obj, '__class__'):
ret.append('__class__')
ret.extend(rlcompleter.get_class_members(obj.__class__))
ret = list(set(ret))
return ret
class Thing(object):
pass
print(get_object_attrs(Thing))
prints
['__module__', '__format__', '__itemsize__', '__str__', '__reduce__', '__weakrefoffset__', '__dict__', '__sizeof__', '__weakref__', '__lt__', '__init__', '__setattr__', '__reduce_ex__', '__subclasses__', '__new__', '__abstractmethods__', '__class__', '__mro__', '__base__', '__bases__', '__dictoffset__', '__call__', '__doc__', '__ne__', '__getattribute__', '__instancecheck__', '__subclasscheck__', '__subclasshook__', '__gt__', '__name__', '__eq__', 'mro', '__basicsize__', '__flags__', '__delattr__', '__le__', '__repr__', '__hash__', '__ge__']
From which we can obtain a list of attributes in Thing
not listed by dir
:
>>> print(set(get_object_attrs(Thing)) - set(dir(Thing)))
set(['__ne__', '__abstractmethods__', '__subclasses__', '__eq__', '__instancecheck__', '__base__', '__flags__', '__mro__', '__le__', '__basicsize__', '__bases__', '__dictoffset__', '__weakrefoffset__', '__call__', '__name__', '__lt__', '__subclasscheck__', '__gt__', '__itemsize__', '__ge__', 'mro'])
get_class_members(cls)
collects attributes from cls
and all the bases of cls
.
Thus, to get a more complete list of attributes, you must add to dir
the attributes of the object's class, and all the attributes of the object's class's bases.