лично я бы реализовать это следующим образом:
#! /usr/bin/python3
import copy
class Room:
def __init__ (self, state = 'Initial'):
self.state = state
self.history = []
def morph (self, state):
clone = copy.deepcopy (self)
self.state = state
self.history.append (clone)
Имейте в виду, что мне делать, если ваш реальный не знаю У установки есть некоторые функции, которые ограничивают глубокое копирование.
Это дает:
>>> r = Room ('Kitchen')
>>> r.morph ('Loo')
>>> r.morph ('Spaceship')
>>> r.state
'Spaceship'
>>> [a.state for a in r.history]
['Kitchen', 'Loo']
>>> [type (a) for a in r.history]
[<class 'test.Room'>, <class 'test.Room'>]
Я думаю, как правило, вам не нужно, чтобы сохранить все состояние объекта, но только атрибуты, которые стоит отслеживать. Вы можете упаковать это поведение в декоратор вдоль этих линий:
#! /usr/bin/python3
import datetime
import copy
class Track:
def __init__ (self, *args, saveState = False):
self.attrs = args
self.saveState = saveState
def __call__ (self, cls):
cls._track = []
this = self
oGetter = cls.__getattribute__
def getter (self, attr):
if attr == 'track': return self._track
if attr == 'trackTrace': return '\n'.join ('{}: "{}" has changed to "{}"'.format (*t) for t in self._track)
return oGetter (self, attr)
cls.__getattribute__ = getter
oSetter = cls.__setattr__
def setter (self, attr, value):
if attr in this.attrs:
self._track.append ((datetime.datetime.now(), attr, copy.deepcopy (value) if this.saveState else value))
return oSetter (self, attr, value)
cls.__setattr__ = setter
return cls
Теперь мы можем использовать этот декоратор так:
@Track ('holder')
class Book:
def __init__ (self, title):
self.title = title
self.holder = None
self.price = 8
class Person:
def __init__ (self, firstName, lastName):
self.firstName = firstName
self.lastName = lastName
def __str__ (self):
return '{} {}'.format (self.firstName, self.lastName)
r = Book ('The Hitchhiker\'s Guide to the Galaxy')
p = Person ('Pedro', 'Párramo')
q = Person ('María', 'Del Carmen')
r.holder = p
r.price = 12
r.holder = q
q.lastName = 'Del Carmen Orozco'
print (r.trackTrace)
При вызове с @Track ('holder')
, он дает:
2013-10-01 14:02:43.748855: "holder" has changed to "None"
2013-10-01 14:02:43.748930: "holder" has changed to "Pedro Párramo"
2013-10-01 14:02:43.748938: "holder" has changed to "María Del Carmen Orozco"
Если он вызван с @Track ('holder', 'price')
, он дает:
2013-10-01 14:05:59.433086: "holder" has changed to "None"
2013-10-01 14:05:59.433133: "price" has changed to "8"
2013-10-01 14:05:59.433142: "holder" has changed to "Pedro Párramo"
2013-10-01 14:05:59.433147: "price" has changed to "12"
2013-10-01 14:05:59.433151: "holder" has changed to "María Del Carmen Orozco"
При вызове с @Track ('holder', saveState = True)
, он дает:
2013-10-01 14:06:36.815674: "holder" has changed to "None"
2013-10-01 14:06:36.815710: "holder" has changed to "Pedro Párramo"
2013-10-01 14:06:36.815779: "holder" has changed to "María Del Carmen"
Добро пожаловать в StackOverflow! Прямо сейчас, похоже, ваш вопрос: «Есть ли лучший способ сделать это?» Конечно, что такое «лучший» способ сделать что-то довольно субъективно (один способ может быть проще скомпилировать, другой может работать быстрее, другой - меньше памяти, другой - для сохранения базы данных). Таким образом, было бы невозможно, чтобы на этот вопрос был один ответ, поэтому StackOverflow - не лучшее место для получения такой обратной связи. Если вы ищете общие комментарии к своему коду, посмотрите на codereview.stackexchange.com. –
Кроме того: 'def __init __ (self, current =" Any ", history = []):' означает, что каждая 'room', которая не передала значение для истории при инициализации, будет делиться * той же * историей. IOW, один 'history' список создается, когда' def' выполняется, а не каждый раз, когда объект создан. Прочитайте [этот вопрос] (http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument) об изменчивых аргументах по умолчанию для деталей. – DSM
Если история сохранена в списке, вам действительно нужно отслеживать self.current по отдельности? Это всегда должен быть последний добавленный элемент. – tom