How to get a complete list of object's methods and attributes? [duplicate]
Asked Answered
J

5

252
dir(re.compile(pattern)) 

does not return pattern as one of the lists's elements. Namely it returns:

['__copy__', '__deepcopy__', 'findall', 'finditer', 'match', 'scanner', 'search', 'split', 'sub', 'subn']

According to the manual, it is supposed to contain

the object's attributes' names, the names of its class's attributes, and recursively of the attributes of its class's base classes.

It says also that

The list is not necessarily complete.

Is there a way to get the complete list? I always assumed that dir returns a complete list but apparently it does not...

Also: is there a way to list only attributes? Or only methods?

Edit: this is actually a bug in python -> supposedly it is fixed in the 3.0 branch (and perhaps also in 2.6)

Jaundiced answered 10/10, 2008 at 12:18 Comment(4)
using dir() or the inspect module is generally the right way to do it. Did you use re module just as an example or do you want to achieve a special goal?Inness
Are you sure that the pattern is actually kept as data once compiled? I was under the impression that the point of compiling a pattern was to produce the finite state automata necessary to parse the given pattern.Matney
@hop cannot dir be sidestepped by classes? For example, they can make their on __dir__()Paradise
ytpillai: correct, but only in Python 3. Even so, the question is, whether such a class would fall under the "general case"Inness
K
149

For the complete list of attributes, the short answer is: no. The problem is that the attributes are actually defined as the arguments accepted by the getattr built-in function. As the user can reimplement __getattr__, suddenly allowing any kind of attribute, there is no possible generic way to generate that list. The dir function returns the keys in the __dict__ attribute, i.e. all the attributes accessible if the __getattr__ method is not reimplemented.

For the second question, it does not really make sense. Actually, methods are callable attributes, nothing more. You could though filter callable attributes, and, using the inspect module determine the class methods, methods or functions.

Kerri answered 10/10, 2008 at 12:25 Comment(7)
inpect.getmembers(re.compile(pattern)) does not yield pattern as a member either, so it probably uses dir internally... This sucks!Overtone
I could also use callable to check if they are methods, but that is not the point... The point is I cannot trust dir to return even the list of attributes that are actually publicly visible...Overtone
inspect is meant to be "at least as" trustworthy as dir(). on the other hand, re is a very complicated moduleInness
What do you define by "publicly visible" ? If you mean "can be accessed", then that is a lost cause for the reason given. Otherwise, 'dir' always return the list of attributes accessible with the default implementation of getattr.Kerri
Well, take a look at the other answer. There is some notion of public visibility in ppython, hence the dir in order for the objects to control what is returned. Still, I came across this cause I use dir in the interactive shell like all the time :D. Anyway, thans.Overtone
dir(my_class) returns something different than my_class.__dict__.keys(). the former also outputs the methods of the class like init and docKilogram
What about help()? :PParadise
D
61

That is why the new __dir__() method has been added in python 2.6

see:

Donahoe answered 10/10, 2008 at 14:46 Comment(3)
I get this error: >> dir__(pyrenderdoc) Traceback (most recent call last): File "<string>", line 1, in <module> NameError: name '__dir' is not definedMalemute
__dir__() is a method on object, not a function - please read the links in the answer and thisDonahoe
One-liner to pprint all attributes and their values: pprint({k:getattr(ojb,k) for k in obj.__dir__()})Ridgeway
M
22

Here is a practical addition to the answers of PierreBdR and Moe:

  • For Python >= 2.6 and new-style classes, dir() seems to be enough.
  • For old-style classes, we can at least do what a standard module does to support tab completion: in addition to dir(), look for __class__, and then to go for its __bases__:

    # code borrowed from the rlcompleter module
    # tested under Python 2.6 ( sys.version = '2.6.5 (r265:79063, Apr 16 2010, 13:09:56) \n[GCC 4.4.3]' )
    
    # or: from rlcompleter import get_class_members
    def get_class_members(klass):
        ret = dir(klass)
        if hasattr(klass,'__bases__'):
            for base in klass.__bases__:
                ret = ret + get_class_members(base)
        return ret
    
    
    def uniq( seq ): 
        """ the 'set()' way ( use dict when there's no set ) """
        return list(set(seq))
    
    
    def get_object_attrs( obj ):
        # code borrowed from the rlcompleter module ( see the code for Completer::attr_matches() )
        ret = dir( obj )
        ## if "__builtins__" in ret:
        ##    ret.remove("__builtins__")
    
        if hasattr( obj, '__class__'):
            ret.append('__class__')
            ret.extend( get_class_members(obj.__class__) )
    
            ret = uniq( ret )
    
        return ret
    

(Test code and output are deleted for brevity, but basically for new-style objects we seem to have the same results for get_object_attrs() as for dir(), and for old-style classes the main addition to the dir() output seem to be the __class__ attribute.)

Mooneyham answered 25/4, 2012 at 10:19 Comment(0)
M
11

Only to supplement:

  1. dir() is the most powerful/fundamental tool. (Most recommended)
  2. Solutions other than dir() merely provide their way of dealing the output of dir().

    Listing 2nd level attributes or not, it is important to do the sifting by yourself, because sometimes you may want to sift out internal vars with leading underscores __, but sometimes you may well need the __doc__ doc-string.

  3. __dir__() and dir() returns identical content.
  4. __dict__ and dir() are different. __dict__ returns incomplete content.
  5. IMPORTANT: __dir__() can be sometimes overwritten with a function, value or type, by the author for whatever purpose.

    Here is an example:

    \\...\\torchfun.py in traverse(self, mod, search_attributes)
    445             if prefix in traversed_mod_names:
    446                 continue
    447             names = dir(m)
    448             for name in names:
    449                 obj = getattr(m,name)
    

    TypeError: descriptor __dir__ of 'object' object needs an argument

    The author of PyTorch modified the __dir__() method to something that requires an argument. This modification makes dir() fail.

  6. If you want a reliable scheme to traverse all attributes of an object, do remember that every pythonic standard can be overridden and may not hold, and every convention may be unreliable.

Mm answered 17/10, 2018 at 3:42 Comment(0)
S
6

This is how I do it, useful for simple custom objects to which you keep adding attributes:

Given an object created with obj = type("Obj",(object,),{}), or by simply:

class Obj: pass
obj = Obj()

Add some attributes:

obj.name = 'gary'
obj.age = 32

then, to obtain a dictionary with only the custom attributes:

{key: value for key, value in obj.__dict__.items() if not key.startswith("__")}

# {'name': 'gary', 'age': 32}
Symbolism answered 2/9, 2016 at 7:7 Comment(1)
list of all attributes in Python 3.x: {key: value for key, value in obj.__dict__.items() if not key.startswith("__")}['_declared_fields'].keys()Plumate

© 2022 - 2024 — McMap. All rights reserved.