14

我在编写一个将类映射到简单表视图的小 GUI 库时遇到了这个问题。某种类型的每个类成员 = 列,列的顺序很重要。但...

class Person(object):

    name = None
    date_of_birth = None
    nationality = None
    gender = None
    address = None
    comment = None


for member in Person.__dict__.iteritems():
    if not member[1]:
        print member[0]

输出:

comment
date_of_birth
name
address
gender
nationality
...

呃,奥德都搞混了……期望的输出:

name
date_of_birth
nationality
gender
address
comment

有没有办法在不维护额外OrderedDict()列的情况下做到这一点?

4

3 回答 3

10

在 Python3 中,通过使用PEP3115是可能的,它允许您在构建类时覆盖元类中的 dict 类型(例如,使用跟踪插入顺序的 OrderedDict)。这是这种方法的一个实现:

class OrderedMeta(type):
    @classmethod
    def __prepare__(metacls, name, bases): 
        return OrderedDict()

    def __new__(cls, name, bases, clsdict):
        c = type.__new__(cls, name, bases, clsdict)
        c._orderedKeys = clsdict.keys()
        return c

class Person(metaclass=OrderedMeta):
    name = None
    date_of_birth = None
    nationality = None
    gender = None
    address = None
    comment = None

for member in Person._orderedKeys:
    if not getattr(Person, member):
        print(member)

在 Python2 中,这要复杂得多。这将是可以通过一些相当 hacky 的东西来实现的,比如自省源代码,并从 AST 中计算出定义顺序,但这可能比它的价值要麻烦得多。

于 2012-07-02T15:20:49.053 回答
4

如果您只需要变量的集合,也许您应该使用 anamedtuple来代替。它还维护字段的顺序(因为它是一个元组)。

from collections import namedtuple
Person = namedtuple('Person', ('name',
                               'data_of_birth',
                               'nationality',
                               'gender',
                               'address',
                               'comment'))
print Person._fields
于 2012-07-02T14:55:55.683 回答
1

好的,这本身不是答案,而是仅在原始问题的上下文中有效的解决方法(“特定类型的每个类成员 [这是一个实例] = 列,并且列的顺序很重要”)。_count解决方案是在类中引入一个类变量CertainType,并在每次实例化时递增它。之后,CertainType 的所有类成员都被打包到一个列表中,该列表使用排序key=attrgetter('_count')

P.S. Omitting that "which is an instance" part was a mistake on my part and it has limited range of solutions considerably. Sorry for that.

于 2012-07-03T19:19:11.117 回答