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

发布于 2024-07-14 12:47:09 字数 344 浏览 6 评论 0原文

以下代码

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) 并解析它之外,还有其他方法吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

初心未许 2024-07-21 12:47:09

请注意,inspect 中已经为您完成了解析 - 看一下 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)

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)

墨洒年华 2024-07-21 12:47:09

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

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

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

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

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

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

The findsource function actually searches trough the source file and looks for likely candidates if it is given a class-object.

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

夜司空 2024-07-21 12:47:09

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

说来避免使用 eval

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

另外,我会通过简单地在循环中 。 请注意,您也可以只迭代 A.__dict__ 中的键/值对

No, you can't get those attributes in the order you're looking for. Python attributes are stored in a dict (read: hashmap), which has no awareness of insertion order.

Also, I would avoid the use of eval by simply saying

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

in your loop. Note that you can also just iterate through key/value pairs in A.__dict__

嘿哥们儿 2024-07-21 12:47:09

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

*:这实际上是可能的,但这需要装饰器或可能的元类黑客。 您对其中任何一个感兴趣吗?

AFAIK, no -- there isn't*. This is because all of a class's attributes are stored in a dictionary (which is, as you know, unordered).

*: it might actually be possible, but that would require either decorators or possibly metaclass hacking. Do either of those interest you?

梦亿 2024-07-21 12:47:09
class ExampleObject:
    def example2():
        pass
    
    def example1():
        pass

context = ExampleObject

def sort_key(item):
    return inspect.findsource(item)[1]

properties = [
    getattr(context, attribute) for attribute in dir(context)
    if callable(getattr(context, attribute)) and 
    attribute.startswith('__') is False
]
properties.sort(key=sort_key)

print(properties)

应该打印出:

[,]

我也需要在我正在构建的某些编译器中使用它,这被证明非常有用。

class ExampleObject:
    def example2():
        pass
    
    def example1():
        pass

context = ExampleObject

def sort_key(item):
    return inspect.findsource(item)[1]

properties = [
    getattr(context, attribute) for attribute in dir(context)
    if callable(getattr(context, attribute)) and 
    attribute.startswith('__') is False
]
properties.sort(key=sort_key)

print(properties)

Should print out:

[<function ExampleObject.example2 at 0x7fc2baf9e940>, <function ExampleObject.example1 at 0x7fc2bae5e790>]

I needed to use this as well for some compiler i'm building, and this proved very useful.

梦幻的味道 2024-07-21 12:47:09

我并不是想在这里表现得圆滑,但是您是否可以按字母顺序组织源代码中的类? 我发现当一个文件中有很多类时,这本身就很有用。

I'm not trying to be glib here, but would it be feasible for you to organize the classes in your source alphabetically? i find that when there are lots of classes in one file this can be useful in its own right.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文