порядок назначения атрибутов в определении класса - PullRequest
4 голосов
/ 06 января 2010

Я хочу определить класс следующим образом:

class List(Base):
    hp = Column(int,...)
    name = Column(str,...)

Этот класс представляет список, я могу определить / изменить / кодировать класс Base и Column. Есть способ узнать порядок, в котором я определил атрибуты hp / names? Например, я хочу определить метод, который может сделать это:

l = List()
l.show()
[(hp,16),(name,roger)] # in this order

Ответы [ 3 ]

7 голосов
/ 06 января 2010

Внутри определения атрибутов хранятся в словаре, который не сохраняет порядок элементов. Возможно, вы можете изменить обработку атрибутов в базовом классе или сохранить порядок создания, например:

class Column:
    creation_counter = 0

    def __init__(self):
            self.creation_counter = Column.creation_counter
            Column.creation_counter += 1

class Base:
    def show(self):
        fields = [(name, (obj, obj.value)) for name, obj in self.__class__.__dict__.items() if isinstance(obj, Column)] 
        fields.sort(lambda (name1, (obj1, value1)), (name2, (obj2, value2)): cmp(obj1.creation_counter, obj2.creation_counter))
        return fields

Django сохраняет порядок полей формы аналогичным образом, хотя и более сложным. Если вам интересно, посмотрите на источник Django форм и полей

0 голосов
/ 06 января 2010

Атрибуты класса и экземпляра изначально неупорядочены, поскольку они хранятся в словаре.

Есть несколько вариантов:

1) классы, определенные с помощью __slots__, не используют словарь, и пространство для атрибутов предварительно выделяется. Я предполагаю, что атрибуты, следовательно, упорядочены, поэтому в принципе должна быть возможность вывести данные. Однако существуют проблемы с использованием слотов, и это не рекомендуется.

2) добавить атрибут класса list / tuple в класс с порядком атрибута.

3) использовать объект collection.namedtuple для хранения атрибутов. Именованный кортеж - это кортеж, в котором вы можете давать имена элементам, и поэтому он похож на структуру C. Это будет работать только с Python 2.6 и выше. Поскольку кортежи являются неизменяемыми, вы не сможете изменять созданные атрибуты - это может быть или не быть проблемой в зависимости от класса.

Edit:

Отражение __slots__ не сработает, поскольку я думаю, что они применяются только к экземплярам, ​​а не к атрибутам класса.

0 голосов
/ 06 января 2010

Я думаю, вы хотите что-то вроде этого:

import inspect

class List(Base):
    hp = Column(int,...)
    name = Column(str,...)

    def show(self):
        public_bits = [(x, getattr(self, x)) for x in dir(self) if not x.startswith('__')]
        return [(x, y) for (x, y) in public_bits if not inspect.ismethod(y)]

К сожалению, dir возвращает атрибуты в алфавитном порядке, так что это может не совсем решить вашу проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...