Как перебирать атрибуты класса в том порядке, в котором они были определены? [дубликат]
этот вопрос уже есть ответ здесь:
Python поставляется с удобным dir()
функция, которая будет перечислять содержимое класса для вас. Например, для этого класса:
class C:
i = 1
a = 'b'
dir(C)
будет возвращение
['__doc__', '__module__', 'a', 'i']
это здорово, но обратите внимание, как порядок 'a'
и 'i'
теперь отличается от того порядка, в котором они были определены.
как я могу перебирать атрибуты C (потенциально игнорируя встроенные атрибуты doc & module) в том порядке, в котором они были определены? Для класса C выше, будет 'i'
затем 'a'
.
добавление: - Я работаю над некоторым кодом сериализации / регистрации, в котором я хочу сериализовать атрибуты в порядке они были определены так, чтобы выходные данные были похожи на код, который создал класс.
4 ответов
Я не думаю, что это возможно в Python 2.X. Когда члены класса предоставляются __new__
метод они даны как словарь, поэтому порядок уже был потерян в этот момент. Поэтому даже метаклассы не могут помочь вам здесь (если нет дополнительных функций, которые я пропустил).
в Python 3 Вы можете использовать новый __prepare__
специальный метод для создания упорядоченного dict (это даже приведено в качестве примера в PEP 3115).
Я новичок в python, поэтому мое решение может быть неэффективным
class Q:
def __init__(self):
self.a = 5
self.b = 10
if __name__ == "__main__":
w = Q()
keys = w.__dict__.keys()
for k in keys:
print "Q.%s = %d"%(k,w.__dict__[k])
вывод:
Q.a = 5
Q.b = 10
поставить этот метод в свой класс
def __setattr__(self, attr, value):
if attr not in dir(self):
if attr == "__ordered_fields__":
super.__setattr__(self, attr, value)
else:
if not hasattr(self, "__ordered_fields__"):
setattr(self, "__ordered_fields__", [])
self.__ordered_fields__.append(attr)
super.__setattr__(self, attr, value)
и чтобы привести поля в порядок, просто сделайте что-то вроде:
print(self.__ordered_fields__)
эта информация недоступна, так как атрибуты хранятся в dict, который по своей сути неупорядочен. Python не хранит эту информацию о заказе нигде.
Если вы хотите, чтобы ваш формат сериализации хранил вещи в определенном порядке, вы бы указать это порядок явно. Вы не будете использовать dir
, который содержит вещи, о которых вы не знаете или не заботитесь, вы бы явно предоставили список (или что-то еще), описывающий, что сериализовать.