Обтекание объекта Python - PullRequest
1 голос
/ 19 мая 2009

Я бы хотел сериализовать объекты Python в и из формата plist (это можно сделать с помощью plistlib). Моя идея заключалась в том, чтобы написать класс PlistObject, который оборачивает другие объекты:

def __init__(self, anObject):
     self.theObject = anObject

и предоставляет метод записи:

def write(self, pathOrFile):
    plistlib.writeToPlist(self.theObject.__dict__, pathOrFile)

Теперь было бы неплохо, если бы PlistObject вел себя так же, как сам обернутый объект, а это означает, что все атрибуты и методы каким-то образом «перенаправляются» в обернутый объект. Я понимаю, что методы __getattr__ и __setattr__ могут использоваться для сложных операций с атрибутами:

    def __getattr__(self, name):
         return self.theObject.__getattr__(name)

Но затем, конечно, я столкнулся с проблемой, что конструктор теперь производит бесконечную рекурсию, поскольку также self.theObject = anObject пытается получить доступ к обернутому объекту.

Как я могу избежать этого? Если вся идея кажется плохой, скажи мне тоже.

Ответы [ 3 ]

3 голосов
/ 19 мая 2009

Если я что-то упустил, это будет прекрасно работать:

def __getattr__(self, name):
    return getattr(self.theObject, name)

Редактировать: для тех, кто думает, что поиск self.theObject приведет к бесконечному рекурсивному вызову __getattr__, позвольте мне показать вам:

>>> class Test:
...     a = "a"
...     def __init__(self):
...         self.b = "b"
...     def __getattr__(self, name):
...         return 'Custom: %s' % name
... 
>>> Test.a
'a'
>>> Test().a
'a'
>>> Test().b
'b'
>>> Test().c
'Custom: c'

__getattr__ вызывается только как last resort . Поскольку theObject можно найти в __dict__, никаких проблем не возникает.

2 голосов
/ 19 мая 2009

Но затем, конечно, я столкнулся с проблемой, что конструктор теперь производит бесконечную рекурсию, поскольку также self.theObject = anObject пытается получить доступ к обернутому объекту.

Именно поэтому в руководстве предлагается, чтобы вы делали это для всех «реальных» обращений к атрибутам.

theobj = object.__getattribute__(self, "theObject")
1 голос
/ 20 мая 2009

Я рад видеть, что другие смогли помочь вам с рекурсивным вызовом __getattr__. Поскольку вы попросили дать комментарии по поводу общего подхода к сериализации в plist, я просто хотел поделиться с вами несколькими мыслями.

Реализованная в Python реализация plist обрабатывает только базовые типы и не предоставляет никакого механизма расширения для инструктирования по сериализации / десериализации сложных типов. Например, если вы определяете пользовательский класс, writePlist не сможет помочь, как вы обнаружили, поскольку вы передаете экземпляр __dict__ для сериализации.

Это имеет несколько последствий:

  1. Вы не сможете использовать это для сериализации любых объектов, содержащих другие объекты неосновного типа, без преобразования их в __dict__ и т. Д. Рекурсивно для всего сетевого графа.

  2. Если вы катите свой собственный обходчик сетевого графика для сериализации всех неосновных объектов, которые могут быть достигнуты, вам придется беспокоиться о кругах на графике, где один объект имеет другой в свойстве, которое, в свою очередь, содержит ссылка на первую и т. д. и т. д.

Учитывая это, вы можете вместо этого взглянуть на рассол, поскольку он может справиться со всем этим и многим другим. Если вам нужен формат plist по другим причинам, и вы уверены, что можете придерживаться «простых» объектных диктов, то вы можете просто использовать простую функцию ... пытаясь заставить PlistObject макетировать каждую возможную функцию в содержании Объект - это лук с потенциально большим количеством слоев, так как вам нужно использовать все возможности упакованного экземпляра.

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

def to_plist(obj, f_handle):
    writePlist(obj.__dict__, f_handle)

Я знаю, что это не выглядит очень привлекательно, но, на мой взгляд, это гораздо более приемлемо, чем обертка, учитывая строгие ограничения формата plist, и, конечно, лучше, чем искусственное принудительное наследование всех объектов в вашем приложении от наследования. общий базовый класс, когда в вашей бизнес-области нет ничего, что фактически указывало бы на то, что эти разрозненные объекты связаны между собой.

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