Итерации через членов класса в порядке их объявления

У меня возникла проблема с написанием небольшой библиотеки 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
...

ugh, кто-то все перепутал... желаемый результат:

name
date_of_birth
nationality
gender
address
comment

Есть ли способ сделать это, не поддерживая дополнительные столбцы OrderedDict()?

Ответ 1

Это возможно в 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 это намного сложнее. Это было бы осуществимо с чем-то довольно взломанным, как интроспекция источника, и разработка порядка определения из АСТ, но это, вероятно, намного больше проблем, чем это стоит.

Ответ 2

Если вам нужно всего лишь совокупность переменных, возможно, вы должны использовать namedtuple. Он также поддерживает порядок полей (как кортеж).

from collections import namedtuple
Person = namedtuple('Person', ('name',
                               'data_of_birth',
                               'nationality',
                               'gender',
                               'address',
                               'comment'))
print Person._fields

Ответ 3

Хорошо, это не ответ как таковой, а обходной путь, который работает только в контексте исходного вопроса ( "Каждый член класса [который является экземпляром] столбца определенного типа= и порядок столбцов важно" ). Решение состоит в том, чтобы ввести переменную класса _count в класс CertainType и увеличить ее при каждом экземпляре. После этого все члены класса SomeType упаковываются в список, который сортируется с помощью key=attrgetter('_count')

P.S. Опуская эту часть, которая является "экземпляром", была ошибкой с моей стороны и значительно ограничила диапазон решений. Извините за это.