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

Я предлагаю вам использовать итераторы вместо счетчиков: "for item in simpleList:" выглядит намного лучше.

Mapad 08.12.2008 12:01
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
83
1
417 592
6

Ответы 6

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

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

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

Вы вообще никогда не создавали экземпляр 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 () больше не поддерживается.

r3t40 14.02.2019 21:13

@TitPoplatnik Просто замените xrange () на range ().

eXPRESS 20.04.2019 11:00

@ironfroggy можно ли получить индекс, по которому объект хранится изнутри класса. Скажем, если класс A находится в позиции 3 в некотором списке, [x, x, x, A, x], возможно ли получить позицию, реализовав метод купола в A.

Alexander Cska 03.07.2019 22:32

Если я правильно понял ваш вопрос, вы спрашиваете способ выполнить глубокую копию объекта. А как насчет использования 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

Повторное использование объекта - глубокая копия или клонирование - распространенная путаница. Иногда вы не можете ответить на вопрос, который кажется вам задающим; иногда вам нужно ответить на вопрос, который они должны были задать.

S.Lott 08.12.2008 15:18

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

Вместо:

x = SimpleClass

тебе нужно:

x = SimpleClass()
x = SimpleClass()является каждый раз воссоздает объект.
neil 22.11.2013 23:23

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

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

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

instancelist[5].attr1 = 'whamma'

лучше быть: instancelist = [MyClass () для _ в диапазоне (29)]

tutormike 31.01.2018 04:44

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

# 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']

Другие вопросы по теме