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
카운터 대신 반복자를 사용하는 것이 좋습니다. "for item in simpleList :"가 훨씬 좋아 보입니다.
Mapad

답변:


70

당신은 근본적인 오해를 보여줍니다.

호출하지 않았으므로 SimpleClass의 인스턴스를 전혀 만들지 않았습니다.

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

또는 클래스가 매개 변수를 받도록하는 경우 대신 목록 이해를 사용할 수 있습니다.

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

2
파이썬 3.x에서는 사용할 수 없음-xrange () func는 더 이상 지원되지 않습니다.
r3t40

3
@TitPoplatnik range () 대신 xrange ()를 바꾸면됩니다.
eXPRESS

@ironfroggy는 객체가 클래스 내에서 저장되는 인덱스를 가져올 수 있습니다. 클래스 A가 일부 목록 [x, x, x, A, x]에서 위치 3에있는 경우 A에서 돔 메서드를 구현하여 위치를 검색 할 수
있습니까?

55

클래스의 개별 인스턴스로 목록을 채우려면 목록 선언에 for 루프를 사용할 수 있습니다. * 곱하기는 각 사본을 동일한 인스턴스에 연결합니다.

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

그런 다음 목록의 색인을 통해 인스턴스에 액세스하십시오.

instancelist[5].attr1 = 'whamma'

3
더 나은 방법 : instancelist = [MyClass () for _ in range (29)]
tutormike

11

단순히 속성을 기반으로 데이터를 출력하는 데 사용하는 경우 일부에서 제안하는 것처럼 SimpleClass 개체를 매번 다시 만들 필요는 없습니다. 그러나 실제로 클래스의 인스턴스를 만드는 것은 아닙니다. 당신은 단순히 클래스 객체 자체에 대한 참조를 만드는 것입니다. 따라서 인스턴스 속성 대신 동일한 클래스 속성에 대한 참조를 목록에 계속 추가합니다.

대신에:

x = SimpleClass

당신은 필요합니다 :

x = SimpleClass()

7
x = SimpleClass() 되는 개체마다 시간을 다시.
neil

5

동일한 인스턴스의 상태를 지속적으로 수정하는 대신 매번 새 인스턴스를 만듭니다. 이때 새 인스턴스는 올바른 상태를 갖습니다.

또는 각 단계에서 원본이 아닌 명시 적으로 만들어진 객체 사본 ( 이 페이지 의 힌트 사용 )을 저장합니다.


3

내가 당신의 질문을 올바르게 이해했다면, 당신은 객체의 딥 카피를 실행하는 방법을 요청합니다. 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)를 볼 수 있습니다.


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']
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.