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

mol*_*ule 4 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
Run Code Online (Sandbox Code Playgroud)

输出

C
D
Run Code Online (Sandbox Code Playgroud)

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

D
C
Run Code Online (Sandbox Code Playgroud)

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

Bri*_*ian 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"))
Run Code Online (Sandbox Code Playgroud)

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


zwe*_*nde 5

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

另外,我会通过简单地说避免使用eval

if type(getattr(A, d)) is types.ClassType:
    print d
Run Code Online (Sandbox Code Playgroud)

在你的循环中.请注意,您也可以只迭代键/值对A.__dict__


Mar*_*rot 5

inspect模块也具有该findsource功能。它返回源代码行和定义对象的行号的元组。

>>> import inspect
>>> import StringIO
>>> inspect.findsource(StringIO.StringIO)[1]
41
>>>
Run Code Online (Sandbox Code Playgroud)

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

给定方法、函数、回溯、框架或代码对象,它只是查看co_firstlineno(包含的)代码对象的属性。