Python introspection: how to get an "unsorted" list of object attributes?

Following code

import types class A: class D: pass class C: pass for d in dir(A): if type(eval('A.'+d)) is types.ClassType: print d 

exits

 C D 

How do I get it for output in the order in which these classes were defined in the code? I.e.

 D C 

Is there any way other than using inspect.getsource (A) and parsing this?

+4
source share
5 answers

The inspect module also has a findsource function. It returns a tuple of source lines and the line number where the object is defined.

 >>> import inspect >>> import StringIO >>> inspect.findsource(StringIO.StringIO)[1] 41 >>> 

The findsource function actually searches through the source file and searches for likely candidates if it is given an object class.

For a method-, function-, traceback-, frame- or code-object, it simply looks for the co_firstlineno attribute of the code object (contained).

+4
source

Please note that this parsing has already been done for you when checking - look at inspect.findsource , which looks for a module to determine the class and returns the source and line number. Sorting by this line number (it may also be necessary to separate classes defined in separate modules) should give the correct order.

However, this function does not seem to be documented, and just uses a regular expression to find a string, so it may not be very reliable.

Another option is to use metaclasses or some other way to either implicitly or explicitly order the information for the object. For instance:

 import itertools, operator next_id = itertools.count().next class OrderedMeta(type): def __init__(cls, name, bases, dct): super(OrderedMeta, cls).__init__(name, bases, dct) cls._order = next_id() # Set the default metaclass __metaclass__ = OrderedMeta class A: class D: pass class C: pass print sorted([cls for cls in [getattr(A, name) for name in dir(A)] if isinstance(cls, OrderedMeta)], key=operator.attrgetter("_order")) 

However, this is a rather intrusive change (you need to install a metaclass of any classes that interest you in OrderedMeta)

+8
source

No, you cannot get these attributes in the order you are looking for. Python attributes are stored in a dict file (read: hashmap) that does not know the insertion order.

Also, I would avoid using eval by simply saying

 if type(getattr(A, d)) is types.ClassType: print d 

in your cycle. Note that you can also just A.__dict__ over key / value pairs in A.__dict__

+5
source

AFAIK, no - no *. This is due to the fact that all the attributes of the class are stored in a dictionary (which, as you know, is disordered).

*: perhaps this is possible, but this will require either decorators or metaclasses. Are you interested in any of you?

+1
source

I'm not trying to look here, but is it possible for you to organize the classes in your source alphabetically? I found that when there are many classes in one file, this can be useful on my own.

0
source

All Articles