在Python中创建对象列表


83

我正在尝试创建一个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的元素,以使每个条目都包含对象的不同实例,而不是全部都指向同一实例?


2
我建议您使用迭代器而不是计数器:“对于simpleList:中的项目”看起来要好得多。
Mapad

Answers:


70

您表现出一个基本的误解。

您根本没有创建SimpleClass的实例,因为您没有调用它。

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

或者,如果让类采用参数,则可以使用列表推导。

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

2
不适用于python 3.x-不再支持xrange()函数。
r3t40

3
@TitPoplatnik只需将xrange()替换为range()。
eXPRESS

@ironfroggy可以从类内部获取存储对象的索引。说,如果A类是在第3位在某些列表中,[X,X,X,A,X],是有可能在A.实施穹顶方法来检索位置
亚历山大中央陆军

55

要用单独的类实例填充列表,可以在列表的声明中使用for循环。*乘法会将每个副本链接到同一实例。

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

然后通过列表的索引访问实例。

instancelist[5].attr1 = 'whamma'

3
更好的是:instancelist = [My_Class()for _ in range(29)]
tutormike

11

就像有人建议的那样,如果您只是简单地使用它根据其属性输出数据,则不必每次都重新创建SimpleClass对象。但是,您实际上并不是在创建类的实例;您只是在创建对类对象本身的引用。因此,您要一遍又一遍地将对同一类属性的引用添加到列表中(而不是实例属性)。

代替:

x = SimpleClass

你需要:

x = SimpleClass()

7
x = SimpleClass() 每次都重新创建对象。
2013年

5

每次在每个新实例都具有正确状态的情况下创建一个新实例,而不是不断修改同一实例的状态。

或者,在每个步骤(而不是原始位置)存储对象的显式副本(使用此页面上的提示)。


3

如果我正确理解了您的问题,则您会提出一种执行对象的深层副本的方法。使用copy.deepcopy怎么样?

import copy

x = SimpleClass()

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

Deepcopy是整个对象的递归副本。有关更多参考,请查看python文档:https : //docs.python.org/2/library/copy.html


2
重用对象(深层复制或克隆)是常见的n00b混淆。有时您无法回答看似要问的问题;有时您必须回答他们应该问的问题。
S.Lott

3

我认为这只是说明您正在努力实现的目标:

# 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

运行上面的代码,您将获得:-

[<__main__.Class instance at 0x6311b2c>, 
<__main__.Class instance at 0x63117ec>]
0 uno
1 duo
2 ['uno', 'duo']
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.