Я пытаюсь создать сценарий 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, чтобы каждая запись содержала другой экземпляр объекта, а не все указывали на один и тот же?
Ответы:
Вы демонстрируете фундаментальное непонимание.
Вы вообще никогда не создавали экземпляр SimpleClass, потому что не вызывали его.
for count in xrange(4): x = SimpleClass() x.attr = count simplelist.append(x)
Или, если вы позволите классу принимать параметры, вместо этого вы можете использовать понимание списка.
simplelist = [SimpleClass(count) for count in xrange(4)]
источник
Чтобы заполнить список отдельными экземплярами класса, вы можете использовать цикл for в объявлении списка. Умножение * свяжет каждую копию с одним и тем же экземпляром.
instancelist = [ MyClass() for i in range(29)]
а затем получить доступ к экземплярам через индекс списка.
instancelist[5].attr1 = 'whamma'
источник
Нет необходимости каждый раз воссоздавать объект SimpleClass, как предлагают некоторые, если вы просто используете его для вывода данных на основе его атрибутов. Однако на самом деле вы не создаете экземпляр класса; вы просто создаете ссылку на сам объект класса. Таким образом, вы снова и снова добавляете ссылку на один и тот же атрибут класса в список (вместо атрибута экземпляра).
Вместо:
тебе нужно:
источник
x = SimpleClass()
будет воссоздавать объект каждый раз.Создавайте каждый раз новый экземпляр, при этом каждый новый экземпляр имеет правильное состояние, а не постоянно изменяет состояние одного и того же экземпляра.
В качестве альтернативы сохраняйте явно созданную копию объекта (используя подсказку на этой странице ) на каждом этапе, а не оригинал.
источник
Если я правильно понял ваш вопрос, вы спрашиваете способ выполнить глубокую копию объекта. А как насчет использования copy.deepcopy?
import copy x = SimpleClass() for count in range(0,4): y = copy.deepcopy(x) (...) y.attr1= '*Bob* '* count
Глубокая копия - это рекурсивная копия всего объекта. Для получения дополнительной информации вы можете взглянуть на документацию python: https://docs.python.org/2/library/copy.html
источник
Я думаю, это просто демонстрирует, чего вы пытаетесь достичь:
# 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']
источник