Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python introspection: How to get an 'unsorted' list of object attributes?

The 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

outputs

C
D

How do I get it to 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 that?

like image 884
molicule Avatar asked Dec 02 '22 08:12

molicule


1 Answers

Note that that parsing is already done for you in inspect - take a look at inspect.findsource, which searches the module for the class definition and returns the source and line number. Sorting on that line number (you may also need to split out classes defined in separate modules) should give the right order.

However, this function doesn't seem to be documented, and is just using a regular expression to find the line, so it may not be too reliable.

Another option is to use metaclasses, or some other way to either implicitly or explicitly ordering information to the object. For example:

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 fairly intrusive change (requires setting the metaclass of any classes you're interested in to OrderedMeta)

like image 93
Brian Avatar answered Dec 03 '22 21:12

Brian