2012-04-21 3 views
0

copy.copy() 및 copy.deepcopy() 및 Python의 범위를 사용하는 데 문제가 있습니다. 함수를 호출하고 사전이 인수로 전달됩니다. 사전은 로컬 사전을 복사하지만 사전은 복사 된 값을 보유하지 않습니다.복사/deepcopy 및 변수 범위

def foo (A, B): 
    localDict = {} 
    localDict['name'] = "Simon" 
    localDict['age'] = 55 
    localDict['timestamp'] = "2011-05-13 15:13:22" 
    localDict['phone'] = {'work':'555-123-1234', 'home':'555-771-2190', 'mobile':'213-601-9100'} 

    A = copy.deepcopy(localDict) 

    B['me'] = 'John Doe' 
    return 



def qua (A, B): 
    print "qua(A): ", A 
    print "qua(B): ", B 

    return 


# *** MAIN *** 
# 
# Test 
# 
A = {} 
B = {} 

print "initial A: ", A 
print "initial B: ", B 

foo (A, B) 

print "after foo(A): ", A 
print "after foo(B): ", B 

qua (A, B) 

copy.deepcopy는 "foo"함수 내에서 작동하며 dict A는 localDict의 내용을 갖습니다. 그러나 "foo"의 범위를 벗어나면, dict A는 비어 있습니다. 한편, 키와 값이 할당 된 후, dict B는 'foo'함수를 벗어나 값을 유지합니다.

copy.deepcopy()가 "foo"함수 외부로 복사하는 값을 어떻게 유지합니까?

+0

왜'foo'가'return localDict, B'를하고 코드에서'A, B = foo (A, B)'를 사용하지 않을까요? 그렇게하면 * 작동 할 것이고'copy' 모듈을 전혀 사용할 필요가 없습니다.또한 파이썬의 객체 참조에서 조금 읽으십시오 : http://stackoverflow.com/questions/575196/in-python-why-can-a-function-modify-some-arguments-as-perceived-by-the-caller – Blender

+0

@Blender, 예 그럴 수는 있겠지만 사전을 참조로 전달할 때 deepcopy()가 파이썬 사전에서 범위 문제를 일으키는 이유를 알고 싶습니다. – SQA777

+0

복사는'deepcopy' 또는'copy'가 아닙니다 (복사하려면'dict (otherdict) '를 사용해야합니다.). 파이썬은 객체를 함수로 전달할 때 PHP처럼 작동하지 않으며 일부 객체 만 수정할 수 있습니다. 내가 연결된 질문에 대한 대답을 읽으십시오. – Blender

답변

0

무슨 일이 일어나고있는가 foo() 내부에서 B의 복사본을 만들고 그것을 A에 할당합니다. 새 객체를 같은 이름으로 재 할당하여 인수로 보낸 빈 dict를 섀도 잉합니다. 함수 내부에는 전역 범위에서 A 외부와 완전히 무관 한 A라는 새로운 사전이 있으며 함수가 끝나면 가비지 수집을 통해 실제로 아무 것도 발생하지 않고 B에 'me'키만 추가됩니다.

대신하는 경우 :

A = copy.deepcopy (localDict)

당신은 같은 것을 할, 당신이 예상대로 작동합니다 :

C = copy.deepcopy(localDict) 

A.update(C) 

를하지만 당신이 정말로 원하는 것 같아 복사 모듈과 아무 관련이 없으며 그렇게 될 것입니다. 이 같은 mething :

def foo (A, B): 
    A['name'] = "Simon" 
    A['age'] = 55 
    A['timestamp'] = "2011-05-13 15:13:22" 
    A['phone'] = {'work':'555-123-1234', 'home':'555-771-2190', 'mobile':'213-601-9100'} 

    B['me'] = 'John Doe' 
1

숙고이 : foo 내부 d = {1: 2}이 이름 d 일부 개체를 결합

>>> def foo(d): 
... d = {1: 2} 
... 
>>> d = {3: 4} 
>>> d 
{3: 4} 
>>> foo(d) 
>>> d 
{3: 4} 
>>> 

. 이 이름은 로컬이므로 d 개체를 수정하지 않습니다. 반면에 :

>>> def bar(d): 
... d[1] = 2 
... 
>>> bar(d) 
>>> d 
{1: 2, 3: 4} 
>>> 

그래서이 빠진 사본의 사용과는 아무 상관이없는, 그냥 파이썬 작업의 방법 "변수"입니다.

0

표시되는 동작은 deepcopy()과 관련이 없으며 A 이름을 새 값으로 다시 지정하고 global 키워드를 사용하지 않으면 해당 할당이 이어지지 않습니다. B에 대한 변경 사항이 지속되는 이유는 당신이 변경 가능한 변수를 수정하는 것입니다, 여기 당신이 동작을 얻을 수있는 방법에 대한 두 가지 옵션이 당신이 원하는 있습니다 :

가 대신 localDict를 사용
  • , 단지 A 수정 :

    def foo(A, B): 
        A['name'] = "Simon" 
        A['age'] = 55 
        A['timestamp'] = "2011-05-13 15:13:22" 
        A['phone'] = {'work':'555-123-1234', 'home':'555-771-2190', 'mobile':'213-601-9100'} 
    
        B['me'] = 'John Doe' 
        return 
    
  • 사용 A.update(copy.deepcopy(localDict)) 대신 A = copy.deepcopy(localDict)의 :

    def foo(A, B): 
        localDict = {} 
        localDict['name'] = "Simon" 
        localDict['age'] = 55 
        localDict['timestamp'] = "2011-05-13 15:13:22" 
        localDict['phone'] = {'work':'555-123-1234', 'home':'555-771-2190', 'mobile':'213-601-9100'} 
    
        A.update(copy.deepcopy(localDict)) 
    
        B['me'] = 'John Doe' 
        return