1

Possible Duplicate:
Inspect python class attributes

I need to get a clean list of the names of all attributes defined my me in a class. Lets say I have the next class:

class MyClass(object):
    attr1 = None
    attr2 = 2
    attr3 = "Hello world"

I would like to know if there is something that allows me to do:

>>> some_method(MyClass)  # <- check class
['attr1', 'attr2', 'attr3']
>>> my_class = MyClass()
>>> some_method(my_class)  # <- check instance of MyClass
['attr1', 'attr2', 'attr3']

I can't rely on the built-in method dir since it also returns attributes like __class__, __getattr__ and any method the class has. I mean, I need to get ONLY the attributes defined in the class, not the built-in ones too, neither the methods.

Is that even possible? or is there any way to know what attributes are built-in and which ones are defined by me so that I can loop over the list dir returns and make some filtering?

Thanks in advance for any help!!

Community
  • 1
  • 1
Gerard
  • 9,088
  • 8
  • 37
  • 52

4 Answers4

5

This is a starting point:

>>> [x for x in dir(a) if not x in dir(super(type(a)))]
['__dict__', '__module__', '__weakref__', 'attr1', 'attr2', 'attr3']

Returns everything in an object's dir that isn't from its parent class' dir.

One thing it does well is filter out the methods defined in the class, but not touch instance attributes which happen to be functions.

Kos
  • 70,399
  • 25
  • 169
  • 233
2

Functions are also attributes, there is nothing stopping you from assigning additional functions to a class or an instance at a later time. So you are asking if you can list all attributes that are not functions, and not 'special'.

If you want to list anything that is defined directly on the class or instance, look at the .__dict__ mapping instead. You'll still have to filter that:

import types

def objectAttributes(obj):
    for key, val in obj.__dict__.iteritems():
        if not isinstance(val, (types.FunctionType, types.MethodType)):
            yield key

This'll generate all attribute names that are not functions or methods, which should work both for classes and for instances that had methods assigned to them manually.

To get a list as output, call list(objectAttributes(MyClass)) or list(objectAttributes(myinstance)).

This method does not traverse base classes, and will fall down if you use __slots__ on your class.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
2

You can use the inspect module to do this.

Here's an example:

>>> import inspect
>>> filter(lambda x: not (x.startswith('__') and x.endswith('__')), [a for (a, b) in inspect.getmembers(MyClass, lambda x : (not inspect.ismethod(x) and not inspect.isbuiltin(x)) )])
['attr1', 'attr2', 'attr3']

The basic idea is to run inspect.getmembers to get all the members of some object. This supports both objects as well as classes. Methods and builtins are filtered using the predicate lambda expression supplied as optional argument to inspect.getmembers. Then, list comprehension is used to get just the names of each of the members, and lastly __dict__ etc is filtered out using the Python filter function.

The filtering for __dict__ etc is not very "scientific", but I think it should do for most cases :)

m01
  • 9,033
  • 6
  • 32
  • 58
  • Don't like too much the `startswith` and `endwith` part, but it solves my problem. Thanks a lot :) – Gerard Nov 22 '12 at 19:32
0
t = MyClass()
result = []
for k,v in t.__dict__.items(): #all members of MyClass
    if not hasattr(v, '__call__'):#if it's not  a callable 
        result.append(k)
scripts
  • 1,452
  • 1
  • 19
  • 24