Python内省:如何获得对象属性的“未排序”列表?

时间:2009-03-12 21:04:57

标签: python introspection python-datamodel

以下代码

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

输出

C
D

如何按照代码中定义这些类的顺序输出?即。

D
C

除了使用inspect.getsource(A)并解析之外,还有其他方法吗?

5 个答案:

答案 0 :(得分:8)

请注意,在检查中已经为您完成了解析 - 查看inspect.findsource,它在模块中搜索类定义并返回源和行号。对该行号进行排序(您可能还需要拆分在单独模块中定义的类)应该给出正确的顺序。

但是,这个函数似乎没有记录,只是使用正则表达式来查找行,所以它可能不太可靠。

另一种选择是使用元类或其他方式来隐式或显式地向对象排序信息。例如:

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"))

然而,这是一个相当干扰的变化(需要将您感兴趣的任何类的元类设置为OrderedMeta)

答案 1 :(得分:5)

不,您无法按照您要查找的顺序获取这些属性。 Python属性存储在dict(read:hashmap)中,它不知道插入顺序。

另外,我会通过简单地说

来避免使用eval
if type(getattr(A, d)) is types.ClassType:
    print d
你的循环中的

。请注意,您也可以只遍历A.__dict__

中的键/值对

答案 2 :(得分:4)

inspect模块还具有findsource功能。它返回一个源元组和行号的元组,其中定义了对象。

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

findsource函数实际上会搜索源文件,并在给定类对象的情况下查找可能的候选对象。

给定方法,函数,跟踪,帧或代码对象,它只是查看(包含的)代码对象的co_firstlineno属性。

答案 3 :(得分:1)

AFAIK,不 - 没有*。这是因为所有类的属性都存储在字典中(如您所知,无序)。

*:它实际上可能是可能的,但这需要装饰器或可能需要元类黑客攻击。你们感兴趣吗?

答案 4 :(得分:0)

我不是想在这里搞笑,但你是否可以按字母顺序组织源中的类?我发现当一个文件中有很多类时,这本身就很有用。