inspect.getmembers按顺序?

mpe*_*pen 22 python python-2.6

inspect.getmembers(object[, predicate])
Run Code Online (Sandbox Code Playgroud)

返回按名称排序的(名称,值)对列表中对象的所有成员.

我想使用这种方法,但我不希望对成员进行排序.我希望它们按照定义的顺序返回.有这种方法的替代方案吗?


使用案例:

创建一个这样的表单:

class RegisterForm(Form):
    username = Field(model_field='username', filters=validators.minlength(3))
    password1 = Field(model_field='password', widget=widgets.PasswordInput)
    password2 = Field(widget=widgets.PasswordInput)
    first_name = Field(model_field='first_name')
    last_name = Field(model_field='last_name')
    address = SubForm(form=AddressForm, model_field='address')
Run Code Online (Sandbox Code Playgroud)

我希望字段按照定义的顺序呈现.

Ned*_*der 13

你可以四处寻找方法的行号,不确定其他成员:

import inspect

class A:
    def one(self):
        pass

    def two(self):
        pass

    def three(self):
        pass

    def four(self):
        pass

def linenumber_of_member(m):
    try:
        return m[1].im_func.func_code.co_firstlineno
    except AttributeError:
        return -1

a = A()
l = inspect.getmembers(a)
print l
l.sort(key=linenumber_of_member)
print l
Run Code Online (Sandbox Code Playgroud)

打印:

[('__doc__', None), ('__module__', '__main__'), ('four', <bound method A.four of <__main__.A instance at 0x0179F738>>), ('one', <bound method A.one of <__main__.A instance at 0x0179F738>>), ('three', <bound method A.three of <__main__.A instance at 0x0179F738>>), ('two', <bound method A.two of <__main__.A instance at 0x0179F738>>)]
[('__doc__', None), ('__module__', '__main__'), ('one', <bound method A.one of <__main__.A instance at 0x0179F738>>), ('two', <bound method A.two of <__main__.A instance at 0x0179F738>>), ('three', <bound method A.three of <__main__.A instance at 0x0179F738>>), ('four', <bound method A.four of <__main__.A instance at 0x0179F738>>)]
Run Code Online (Sandbox Code Playgroud)


Sku*_*del 5

通常通过对象的特殊__dict__属性(标准Python字典)查找对象的属性(方法和其他成员).它不保证任何特定的订购.

如果在对象中找不到属性,则会__dict__搜索类(通常驻留方法),依此类推,直到遍历整个继承链为止.

以下是在交互式提示中完成的一些自定义检查,以说明这一点(Python 3.1):

>>> class Klass():
...     def test(self):
...             pass
...
>>> k = Klass()
>>> k.__dict__
{}
>>> k.__class__.__dict__.items()
[('test', <function test at 0x00000000024113C8>), ('__dict__', <attribute '__dic
t__' of 'Klass' objects>), ('__module__', '__main__'), ('__weakref__', <attribut
e '__weakref__' of 'Klass' objects>), ('__doc__', None)]
Run Code Online (Sandbox Code Playgroud)

我是否__init__在Klass中放置了一个构造函数()并通过self它设置了一个属性k.__dict__.

您可以使用自定义元类来规避这一点.该文档包含一个完全符合您要求的示例.

有关OrderedClass示例,请参见本页底部.

不知道你有什么版本的Python,所以我假设最新.

  • @Mark:用于`type`的Python 2.6.5源代码:http://svn.python.org/view/python/tags/r265/Objects/typeobject.c?view = markup我一直在阅读(坦率地说是巨大的)函数`type_new`我认为它将传入的字典复制到一个新的`dict`,这可以解释为什么它最终成为一个`dict`,无论我的测试是什么. (2认同)

mpe*_*pen 5

我认为 Python 2.6 没有__prepare__方法,因此我无法将默认方法替换dict为有序方法。但是,我可以使用 ametaclass__new__方法替换它。我认为不检查行号,只使用创建计数器更容易、更有效。

class MetaForm(type):
    def __new__(cls, name, bases, attrs):
        attrs['fields'] = OrderedDict(
            sorted(
                [(name, attrs.pop(name)) for name, field in attrs.items() if isinstance(field, Field)],
                key=lambda t: t[1].counter
            )
        )
        return type.__new__(cls, name, bases, attrs)

class Form(object):
    __metaclass__ = MetaForm

class Field(object):
    counter = 0
    def __init__(self):
        self.counter = Field.counter
        Field.counter += 1
Run Code Online (Sandbox Code Playgroud)