Я пытаюсь создать сценарий 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)]
Недоступно для python 3.x - функция xrange () больше не поддерживается.
@TitPoplatnik Просто замените xrange () на range ().
@ironfroggy можно ли получить индекс, по которому объект хранится изнутри класса. Скажем, если класс A находится в позиции 3 в некотором списке, [x, x, x, A, x], возможно ли получить позицию, реализовав метод купола в A.
Если я правильно понял ваш вопрос, вы спрашиваете способ выполнить глубокую копию объекта. А как насчет использования 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
Повторное использование объекта - глубокая копия или клонирование - распространенная путаница. Иногда вы не можете ответить на вопрос, который кажется вам задающим; иногда вам нужно ответить на вопрос, который они должны были задать.
Нет необходимости каждый раз воссоздавать объект SimpleClass, как предлагают некоторые, если вы просто используете его для вывода данных на основе его атрибутов. Однако на самом деле вы не создаете экземпляр класса; вы просто создаете ссылку на сам объект класса. Следовательно, вы снова и снова добавляете ссылку на один и тот же атрибут класса в список (вместо атрибута экземпляра).
Вместо:
x = SimpleClass
тебе нужно:
x = SimpleClass()
x = SimpleClass()является каждый раз воссоздает объект.
Чтобы заполнить список отдельными экземплярами класса, вы можете использовать цикл for в объявлении списка. Умножение * свяжет каждую копию с одним и тем же экземпляром.
instancelist = [ MyClass() for i in range(29)]
а затем получить доступ к экземплярам через индекс списка.
instancelist[5].attr1 = 'whamma'
лучше быть: instancelist = [MyClass () для _ в диапазоне (29)]
Я думаю, это просто демонстрирует, чего вы пытаетесь достичь:
# 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']
Я предлагаю вам использовать итераторы вместо счетчиков: "for item in simpleList:" выглядит намного лучше.