Откат объектов, копирование при записи, версионный прокси и т. Д. В Python - PullRequest
2 голосов
/ 27 января 2011

Предпосылка : учитывая объект Python obj, я хочу передать его некоторой случайной функции, и, когда функция будет завершена, мне понадобится опция для сброса obj в исходное состояние.государство.Кроме того, в obj не может быть внесено никаких реальных изменений, поскольку другой код может по-прежнему хотеть получить доступ к его исходному состоянию.


Оптимальное решение должно быть быстрым в обычном случае, когда большое objтолько слегка изменен.Производительность для необычного случая, когда obj необходимо откатить, менее важна.

Эти требования ортогональны решению грубой силы простого копирования объекта: в общем случае это было бы смехотворно медленным,и очень быстрый для необычного отката.

Решение должно, как правило, позволить коду, работающему с объектом, обрабатывать его как обычный объект.Это включает в себя присвоение ему всевозможных атрибутов, включая пользовательские классы.Очевидно, что решение должно учитывать все дерево объектов.Некоторые уступки могут быть необходимы.Примеры ограничений, которые я рассматривал в своих решениях, до сих пор включают требование, чтобы все неосновные типы наследовались от специального базового класса, запрещение диктов и списков в обмен на кортежи, собственный класс dict и т. Д. Могут быть приемлемы большие тайны.

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


Редактировать: ответ Фреда заставил меня осознать пропущенное требование: нельзя вносить изменения в исходный obj, поскольку исходное состояние также ценно.

Ответы [ 2 ]

1 голос
/ 03 февраля 2011

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

Самое простое решение - использовать Copy On Demand . Если у нас есть прокси P нацеливающий объект O: P будет иметь метод __getattr__, поэтому при попытке P.x он попытается скопировать из O.x, сохранив его на P.x в в то же время. Это приводит к тому, что в будущем доступ к P.x никогда не достигнет __getattr__, а изменения к P.x не повлияют на оригинал.

Существует множество деталей реализации:

Ведение списка атрибутов, которые удалены из P; если P объединен с O, удаленные атрибуты должны быть удалены из O. Написание пользовательских подпрограмм глубокого копирования для всех поддерживаемых типов данных, таких как dict, list и т. Д., При этом обязательно заменяйте все объекты O на прокси P в скопированных dict, list , так далее. Запись ProxyDict, ProxyList и т. Д. По желанию. Проверка работоспособности цепочек прокси, то есть прокси для прокси. В основном это означает, что нужно избегать побочных эффектов, когда прокси-серверу необходимо проконтролировать, существует ли атрибут. Реализация методов слияния прокси вниз в прокси-объект и его полного разбиения с копированием оставшихся данных из прокси-объекта.

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

0 голосов
/ 27 января 2011

Взгляните на Памятка шаблон дизайна

Вот пример для Python

...