2016-09-16 5 views
2

У меня есть следующий класс:Получить упорядоченный словарь атрибутов класса внутри __init__

class NewName: 
    def __init__(self): 
     self.Name = None 
     self.DecomposedAlias = OrderedDict([("Prefix", None), 
              ("Measurement", None), 
              ("Direction", None), 
              ("Item", None), 
              ("Location", None), 
              ("Descriptor", None), 
              ("Frame", None), 
              ("RTorigin", None)]) 
     self.Meaning = "" 
     self.SIUnit = OrderedDict([("ScaleFactor", None), 
            ("Offset", None), 
            ("A", None), 
            ("cd", None), 
            ("K", None), 
            ("kg", None), 
            ("m", None), 
            ("mol", None), 
            ("rad", None), 
            ("s", None)]) 
     self.NormalDisplayUnit = OrderedDict([("ScaleFactor", None), 
               ("Offset", None), 
               ("A", None), 
               ("cd", None), 
               ("K", None), 
               ("kg", None), 
               ("m", None), 
               ("mol", None), 
               ("rad", None), 
               ("s", None)]) 
     self.OrientationConvention = "" 
     self.ContactPerson = "" 
     self.Note = "" 
     self.SubType = None 
     self.RefersTo = [] 

Если я создаю экземпляр нового объекта этого класса я могу получить словарь, как это:

mynewname = NewName() 
mynewdict = mynewname.__dict__ 

Что делать, если Я хочу, чтобы mynewdict был заказан таким же образом, что и атрибуты NewName были созданы в его __init__?

Проведя некоторые исследования, я нашел this, но в моем случае я бы просто получил ['__init__']. Есть ли способ указать атрибуты внутри __init__?

Для полноты я должен упомянуть, что я использую Python 3.4.

ответ

1

Вы не можете сделать это, потому что атрибут __init__ вызывается после того, что экземпляр был создан (по __new__()), так что если вы даже переопределить __new__() и использовать __prepare__ метод using a metaclass, вы можете просто получить упорядоченную последовательность (ДИКТ или т. д.) других методов и атрибутов, которые не определены в методе __init__.

Также на основе this mail:

Это просто не возможно иметь что-то другое, чем Словарь как тип-х __dict__. Это преднамеренное ограничение и требуемая оптимизация.

Но это не означает, что вы не можете получить список упорядоченных атрибутов своего класса. Поскольку каждый атрибут устанавливает с помощью __setattr__ метода вы можете просто сохранить свои атрибуты в упорядоченном Словаре переопределения __setattr__ метода:

from collections import OrderedDict 

class NewName: 
    ordered_attrs = OrderedDict() 
    def __setattr__(self, name, val): 
     object.__setattr__(self, name, val) 
     # Use setattr(self, name, val) if you don't want to preserve the attributes in instances `__dict__` 
     NewName.ordered_attrs[name] = val 

    def __init__(self): 
     # your __init__ body 

mynewname = NewName() 
print(list(NewName.ordered_attrs)) 

Выход:

['Name', 'DecomposedAlias', 'Meaning', 'SIUnit', 'NormalDisplayUnit', 'OrientationConvention', 'ContactPerson', 'Note', 'SubType', 'RefersTo'] 

# Output of mynewname.__dict__ 
{'Note': '', 'Meaning': '', 'RefersTo': [], 'SIUnit': OrderedDict([('ScaleFactor', None), ('Offset', None), ('A', None), ('cd', None), ('K', None), ('kg', None), ('m', None), ('mol', None), ('rad', None), ('s', None)]), 'DecomposedAlias': OrderedDict([('Prefix', None), ('Measurement', None), ('Direction', None), ('Item', None), ('Location', None), ('Descriptor', None), ('Frame', None), ('RTorigin', None)]), 'SubType': None, 'Name': None, 'ContactPerson': '', 'NormalDisplayUnit': OrderedDict([('ScaleFactor', None), ('Offset', None), ('A', None), ('cd', None), ('K', None), ('kg', None), ('m', None), ('mol', None), ('rad', None), ('s', None)]), 'OrientationConvention': ''} 

Также в отношении установки атрибутов, основанных на documentation:

Если __setattr__() хочет присвоить атрибуту экземпляра, он должен вызвать метод базового класса с помощью s имя, например, object.__setattr__(self, name, value).

+0

спасибо, теперь я могу получить упорядоченный словарь. Однако после предлагаемой модификации класса, если я попрошу 'mynewdict = mynewname .__ dict__', он возвращает пустой словарь. Вы знаете, почему? – Francesco

+0

@Francesco В этом случае, если вы хотите иметь атрибуты в '' __dict__' экземпляра, вы должны использовать 'object .__ setattr __ (self, name, val)' для установки атрибутов. – Kasramvd

+0

Благодарим за редактирование. Однако я не специалист по питону, и, боюсь, я не понял, что вы имеете в виду. В моем классе я добавил функцию вроде: '@staticmethod def ordered_dict(): return ordered_attrs' , чтобы получить упорядоченный словарь с' mynewdict = mynewname.ordered_dict() '. Как использовать 'object .__ setattr __ (self, name, val)' для получения неупорядоченного словаря, как я получил с помощью mynewdict = mynewname .__ dict__'?Другими словами, после предлагаемой модификации класса я могу по-прежнему каким-то образом стать неупорядоченным словарем? – Francesco