Python在新实例中缓存先前的对象属性

时间:2019-01-15 03:36:29

标签: python django

我遇到了一个奇怪的问题。它从尝试在django中循环创建对象开始。我在模型save()上执行了类似的操作

self.history.append(new_status)

现在,我认为自己是指正在评估的当前实例。但是,当在一个循环中(在单个python进程上)运行self.history时,它会从上次评估开始进行缓存。

因此,在示例中:

for i in range(3):
    job = Job(...properties, exluding history, as that's done in the save() method)
    job.save()

存储在数据库中的作业如下:

job1 - id: 1, history: ['pending']
job2 - id: 2, history: ['pending', 'pending']
job3 - id: 3, history: ['pending', 'pending', 'pending']
... so on

现在,如果django服务器没有重新启动,并且再次调用了此控制器,则将创建作业,从创建的最后一个对象的历史记录开始(因此它将以4个挂起对象开始,然后是下一个5个对象,等等)。

基本上是前X条记录和当前N条记录

我已经能够使用简单的Python进行大量复制:

class Base(object):
    id = None
    name = None
    history = list()

    def __init__(self, id=None, name=None):
        self.id = id
        self.name = name

    def save(self, **kwargs):
        for arg in kwargs:
            self.__setattr__(arg, kwargs.get(arg))


class Queue(Base):
    def save(self, **kwargs):
        self.history.append({'status': 'test'})
        super(Queue, self).save()


items = []
for i in range(5):

    items.append(Queue(
        id=i,
        name=str(i) + '-test'
    ))

for _ in items:
    _.save()
    print(_.history)

在调试器中运行时,您会得到:

[{'status': 'test'}]
[{'status': 'test'}, {'status': 'test'}]
[{'status': 'test'}, {'status': 'test'}, {'status': 'test'}]
[{'status': 'test'}, {'status': 'test'}, {'status': 'test'}, {'status': 'test'}]
[{'status': 'test'}, {'status': 'test'}, {'status': 'test'}, {'status': 'test'}, {'status': 'test'}]

我真的无法弄清楚-闻起来像不是python问题,但是对对象/引用在Python中的工作方式缺乏了解。

任何帮助都会很棒!谢谢。

1 个答案:

答案 0 :(得分:1)

原因是historyclass variable,因此在所有类实例中它都是相同的变量,因此每次在self.history.append({'status': 'test'})中调用Queue时,更改在所有实例的范围内。

我希望history是一个实例变量,应该在方法内部声明它。

编辑

class Base(object):
    id = None
    name = None
    history = list() # <-------- Class variable, global to all instances.

    def __init__(self, id=None, name=None):
        self.id = id
        self.name = name
        self.instance_variable = None # <------- Instance variable, global to all methods of the instance.

        local_variable = None # <------ Local variable, local to the method of the instance

    def save(self, **kwargs):
        for arg in kwargs:
            self.__setattr__(arg, kwargs.get(arg))