Создание списка объектов в Python - PullRequest
72 голосов
/ 08 декабря 2008

Я пытаюсь создать скрипт 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, чтобы каждая запись содержала различный экземпляр объекта, а не все указывающие на один и тот же?

Ответы [ 6 ]

59 голосов
/ 08 декабря 2008

Вы демонстрируете фундаментальное недоразумение.

Вы вообще никогда не создавали экземпляр SimpleClass, потому что вы его не вызывали.

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

Или, если вы позволите классу принимать параметры, вы можете использовать понимание списка.

simplelist = [SimpleClass(count) for count in xrange(4)]
51 голосов
/ 09 декабря 2008

Чтобы заполнить список отдельными экземплярами класса, вы можете использовать цикл for в объявлении списка. * Multiply свяжет каждую копию с одним и тем же экземпляром.

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

, а затем получить доступ к экземплярам через индекс списка.

instancelist[5].attr1 = 'whamma'
10 голосов
/ 08 декабря 2008

Нет необходимости каждый раз воссоздавать объект SimpleClass, как полагают некоторые, если вы просто используете его для вывода данных на основе его атрибутов. Однако вы на самом деле не создаете экземпляр класса; вы просто создаете ссылку на сам объект класса. Поэтому вы добавляете ссылку на один и тот же атрибут класса в список (вместо атрибута экземпляра), снова и снова.

Вместо:

x = SimpleClass

вам нужно:

x = SimpleClass()
5 голосов
/ 08 декабря 2008

Каждый раз создавайте новый экземпляр, где каждый новый экземпляр имеет правильное состояние, а не постоянно изменяйте состояние одного и того же экземпляра.

Альтернативно, сохраняйте явно сделанную копию объекта (используя подсказку на этой странице ) на каждом шаге, а не оригинал.

3 голосов
/ 07 марта 2018

Я думаю, это просто демонстрирует, чего вы пытаетесь достичь:

# 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']
3 голосов
/ 08 декабря 2008

Если я правильно понимаю ваш вопрос, вы спрашиваете способ выполнить глубокую копию объекта. Как насчет использования copy.deepcopy?

import copy

x = SimpleClass()

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

Deepcopy - это рекурсивная копия всего объекта. Для получения дополнительной информации вы можете взглянуть на документацию по питону: https://docs.python.org/2/library/copy.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...