问题描述
我正在尝试提出一种方法来跟踪Python中对象的各种重新编程.例如,我想为一个房间上课.这个房间可以作为厨房"开始存在,然后在任何给定的时间点成为研究".我希望能够跟踪(或记录)房间生活中的所有这些不同阶段.因此,我想到了这一点,并且想知道是否有更好的方法可以做到这一点.或者,也许我缺少了一些东西.不过据我所知,它似乎可以满足我的目的.
I am trying to come up with a way to keep track of various re-incarnations of an object in Python. For example, I would like to have a class for, say, a room. This room could start its existence as a 'kitchen', and then, at any given point in time, become a 'study'. I want to be able to track (or log) all these various phases in the life of my room. So, I came up with this, and am wondering if there is a better way to do this. Or maybe I'm missing something. From what I can tell, though, it appears to work for my purposes.
class room():
def __init__(self,current="Any", history = []):
self.current = childroom(current)
self.history = history
self.history.append(self.current)
def changeroom(self,current = "New"):
self.current = childroom(current)
self.history.append(self.current)
class childroom(room):
def __init__(self,name="Any"):
self.name = name
当我使用此代码时...
When I use this code...
>>> myroom = room("kitchen")
>>> myroom.changeroom("study")
>>> myroom
<__main__.room instance at 0x0000000003139208>
>>> myroom.history
[<__main__.childroom instance at 0x0000000003139288>, <__main__.childroom instance at 0x00000000023F4AC8>]
>>> myroom.history[0].name
'kitchen'
推荐答案
我个人会这样实现:
#! /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)
请记住,我不知道您的实际设置是否具有某些限制深度复制的功能.
Keep in mind, that I don't know if your real setup has some features that restrict deep copying.
这将产生:
>>> 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'>]
我想通常您不需要保存对象的整个状态,而只需保存值得跟踪的属性.您可以按照以下方式将此行为打包到装饰器中:
I guess normally you don't need to save the whole state of an object, but only attributes which are worth tracking. You could pack this behaviour into a decorator along these lines:
#! /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
现在,我们可以像这样使用此装饰器:
Now we can use this decorator like this:
@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')
调用,它将产生:
If called with @Track ('holder')
, it yields:
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')
调用,它将产生:
If called with @Track ('holder', 'price')
, it yields:
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)
调用,它将产生:
If called with @Track ('holder', saveState = True)
, it yields:
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"
这篇关于Python对象历史的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!