在 Python 中创建对象列表

我正在尝试创建一个 Python 脚本,它可以打开几个数据库并比较它们的内容。在创建这个脚本的过程中,我在创建一个列表时遇到了一个问题,这个列表的内容是我创建的对象。

我已经简化了这个程序到它的骨架为这个张贴。首先,我创建一个新类,创建它的一个新实例,为它分配一个属性,然后将它写入一个列表。然后我给这个实例赋一个新值,并再次将它写入一个列表... ... 一次又一次... ..。

问题是,它总是相同的对象所以我只是改变了基本对象。当我读这个列表的时候,我会得到同一个对象的一遍又一遍的重复。

那么如何在循环中将对象写入列表呢?

这是我的简化代码

class SimpleClass(object):
pass


x = SimpleClass
# Then create an empty list
simpleList = []
#Then loop through from 0 to 3 adding an attribute to the instance 'x' of SimpleClass
for count in range(0,4):
# each iteration creates a slightly different attribute value, and then prints it to
# prove that step is working
# but the problem is, I'm always updating a reference to 'x' and what I want to add to
# simplelist is a new instance of x that contains the updated attribute


x.attr1= '*Bob* '* count
print "Loop Count: %s Attribute Value %s" % (count, x.attr1)
simpleList.append(x)


print '-'*20
# And here I print out each instance of the object stored in the list 'simpleList'
# and the problem surfaces.  Every element of 'simpleList' contains the same      attribute value


y = SimpleClass
print "Reading the attributes from the objects in the list"
for count in range(0,4):
y = simpleList[count]
print y.attr1

那么,我如何(追加、扩展、复制或其他) simpleList 的元素,使每个条目包含对象的不同实例,而不是所有指向同一个实例?

425753 次浏览

Create a new instance each time, where each new instance has the correct state, rather than continually modifying the state of the same instance.

Alternately, store an explicitly-made copy of the object (using the hint at this page) at each step, rather than the original.

You demonstrate a fundamental misunderstanding.

You never created an instance of SimpleClass at all, because you didn't call it.

for count in xrange(4):
x = SimpleClass()
x.attr = count
simplelist.append(x)

Or, if you let the class take parameters, instead, you can use a list comprehension.

simplelist = [SimpleClass(count) for count in xrange(4)]

If I understand correctly your question, you ask a way to execute a deep copy of an object. What about using copy.deepcopy?

import copy


x = SimpleClass()


for count in range(0,4):
y = copy.deepcopy(x)
(...)
y.attr1= '*Bob* '* count

A deepcopy is a recursive copy of the entire object. For more reference, you can have a look at the python documentation: https://docs.python.org/2/library/copy.html

It shouldn't be necessary to recreate the SimpleClass object each time, as some are suggesting, if you're simply using it to output data based on its attributes. However, you're not actually creating an instance of the class; you're simply creating a reference to the class object itself. Therefore, you're adding a reference to the same class attribute to the list (instead of instance attribute), over and over.

Instead of:

x = SimpleClass

you need:

x = SimpleClass()

A list comprehension can be used to fill a list with separate instances of a class, like so:

instancelist = [MyClass() for i in range(29)]

This avoids the problem with multiplying a list of one element with *, which re-uses the same object.

I think this simply demonstrates what you are trying to achieve:

# coding: utf-8


class Class():
count = 0
names = []


def __init__(self,name):
self.number = Class.count
self.name = name
Class.count += 1
Class.names.append(name)


l=[]
l.append(Class("uno"))
l.append(Class("duo"))
print l
print l[0].number, l[0].name
print l[1].number, l[1].name
print Class.count, Class.names

Run the code above and you get:-

[<__main__.Class instance at 0x6311b2c>,
<__main__.Class instance at 0x63117ec>]
0 uno
1 duo
2 ['uno', 'duo']