[python] 목록을 딥 카피하는 방법?

List 사본에 문제가 있습니다.

그래서 E0로부터 전화를 받으면을 호출 'get_edge'하여 사본을 만듭니다 . 여기 추측 의 딥 카피 , 나는 통과 로 . 그러나 주요 기능에서. for 루프 이전
의 결과가 for 루프 이후 의 결과와 다른 이유는 무엇 입니까?E0'E0_copy = list(E0)'E0_copyE0E0_copy'karger(E)'
'print E0[1:10]'

아래는 내 코드입니다.

def get_graph():
    f=open('kargerMinCut.txt')
    G={}
    for line in f:
        ints = [int(x) for x in line.split()]
        G[ints[0]]=ints[1:len(ints)]
    return G

def get_edge(G):
    E=[]
    for i in range(1,201):
        for v in G[i]:
            if v>i:
                E.append([i,v])
    print id(E)
    return E

def karger(E):
    import random
    count=200
    while 1:
        if count == 2:
            break
        edge = random.randint(0,len(E)-1)
        v0=E[edge][0]
        v1=E[edge][1]
        E.pop(edge)
        if v0 != v1:
            count -= 1
            i=0
            while 1:
                if i == len(E):
                    break
                if E[i][0] == v1:
                    E[i][0] = v0
                if E[i][1] == v1:
                    E[i][1] = v0
                if E[i][0] == E[i][1]:
                    E.pop(i)
                    i-=1
                i+=1

    mincut=len(E)
    return mincut


if __name__=="__main__":
    import copy
    G = get_graph()
    results=[]
    E0 = get_edge(G)
    print E0[1:10]               ## this result is not equal to print2
    for k in range(1,5):
        E0_copy=list(E0)         ## I guess here E0_coypy is a deep copy of E0
        results.append(karger(E0_copy))
       #print "the result is %d" %min(results)
    print E0[1:10]               ## this is print2



답변

E0_copy깊은 사본이 아닙니다. list()(모두 list(...)testList[:]얕음)을 사용하여 딥 카피를 만들지 않습니다 .

당신은 사용 copy.deepcopy(...)깊은 목록을 복사하는.

deepcopy(x, memo=None, _nil=[])
    Deep copy operation on arbitrary Python objects.

다음 스 니펫을 참조하십시오-

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b   # b changes too -> Not a deepcopy.
[[1, 10, 3], [4, 5, 6]]

이제 deepcopy작업을 참조하십시오

>>> import copy
>>> b = copy.deepcopy(a)
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
>>> a[0][1] = 9
>>> a
[[1, 9, 3], [4, 5, 6]]
>>> b    # b doesn't change -> Deep Copy
[[1, 10, 3], [4, 5, 6]]


답변

많은 프로그래머들이 하나 또는 두 개의 인터뷰 문제를 겪어 링크 목록을 딥 카피해야한다고 생각하지만이 문제는 생각보다 어렵습니다!

파이썬에는 두 가지 유용한 기능을 가진 “복사”라는 모듈이 있습니다

import copy
copy.copy()
copy.deepcopy()

주어진 인수가 복합 데이터 구조 (예 : list ) 인 경우 copy ()는 얕은 복사 함수입니다. 파이썬은 동일한 유형 (이 경우 새 목록 )의 다른 객체를 만들지 만 이전 목록의 모든 것에 대해 참조 만 복사됩니다

# think of it like
newList = [elem for elem in oldlist]

직관적으로, 우리는 deepcopy ()가 동일한 패러다임을 따를 것이라고 가정 할 수 있으며, 유일한 차이점은 각 요소 마다 재귀 적으로 deepcopy를 호출 한다는 것입니다 (mbcoder의 답변과 동일).

그러나 이것은 잘못입니다!

deepcopy ()는 실제로 원래 복합 데이터의 그래픽 구조를 유지합니다.

a = [1,2]
b = [a,a] # there's only 1 object a
c = deepcopy(b)

# check the result
c[0] is a # return False, a new object a' is created
c[0] is c[1] # return True, c is [a',a'] not [a',a'']

이것은 딥 카피 () 프로세스 중에 해시 테이블 (python의 사전)을 사용하여 “old_object ref를 new_object ref에 매핑”하는 데 사용됩니다. 이는 불필요한 중복을 방지하여 복사 된 복합 데이터의 구조를 보존합니다.

공식 문서


답변

목록의 내용이 기본 데이터 유형 인 경우 이해를 사용할 수 있습니다

new_list = [i for i in old_list]

다음과 같이 다차원 목록에 중첩시킬 수 있습니다.

new_grid = [[i for i in row] for row in grid]


답변

귀하의 경우 list elements입니다 immutable objects당신은 그렇지 않으면 사용해야합니다, 이것을 사용할 수 있습니다 deepcopy에서 copy모듈.

list이와 같이 딥 카피에는 가장 짧은 방법을 사용할 수도 있습니다 .

a = [0,1,2,3,4,5,6,7,8,9,10]
b = a[:] #deep copying the list a and assigning it to b
print id(a)
20983280
print id(b)
12967208

a[2] = 20
print a
[0, 1, 20, 3, 4, 5, 6, 7, 8, 9,10]
print b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10]


답변

재귀 딥 카피 기능.

def deepcopy(A):
    rt = []
    for elem in A:
        if isinstance(elem,list):
            rt.append(deepcopy(elem))
        else:
            rt.append(elem)
    return rt

편집 : Cfreak이 언급했듯이 이것은 이미 copy모듈 에서 구현되었습니다 .


답변

목록을 트리로 사용하면 Python의 deep_copy는 다음과 같이 가장 간결하게 작성할 수 있습니다.

def deep_copy(x):
    if not isinstance(x, list): return x
    else: return map(deep_copy, x)


답변

다음은 목록을 딥 카피하는 방법의 예입니다.

  b = [x[:] for x in a]