본문 바로가기
Computer Science/[20-3,4] Python Basic

[Python] 복사본 변수의 변경이 원본에 영향을 미칠 때

by gojw 2020. 4. 3.
class Number:
    def __init__(self, number):
        self.number = number

    def my_function(self):
        self.number[0] = 100
        return self.number

numlist = [1, 2, 3]
num1 = Number(numlist).my_function()

print(num1)
# [100, 2, 3]
print(numlist)
# [100, 2, 3]	# ???

예시 클래스 Number을 보자.

① 생성자 __init__() 메소드로 받은 인자를 인스턴스 변수로 만들어주고

my_function() 메소드로 인덱스가 0인 자리를 100으로 바꾸어주는 클래스이다.

 

우리는 numlist를 만들고, 그 numlist를 인자로 넣은 클래스 객체 num1을 만들었다.

numlist를 클래스 내의 메소드를 통해 조작한 결과가 num1이니까,

num1의 인덱스 0이 100으로 바뀔 것이고, 여기까지는 원하는 대로 되었지만..

문제는 원본 객체 numlist의 인덱스 0도 100으로 바뀐 것을 확인할 수 있다.

 

이유는 id() 함수를 통해 알아낼 수 있다.

>>> print(id(numlist))
# 18761208
>>> print(id(num1))
# 18761208​

id()는 두 객체의 메모리 주소 (memory address)를 확인하는 함수이다.

이 두 객체는 같은 메모리 주소를 가리키고 있다.

__init__() 메소드에서 self.numlist = numlist라는 코드는 numlist의 복사본이 numlist와 같은 객체임을 말한다.

 

따라서 이런 문제를 해결하기 위해서는 단순히 a = b로 복사하는 것이 아니라,

class Number:
    def __init__(self, number):
        self.number = number[:]

    def my_function(self):
        self.number[0] = 100
        return self.number

numlist = [1, 2, 3]
num1 = Number(numlist).my_function()

print(num1)
# [100, 2, 3]
print(numlist)
# [1, 2, 3]
print(id(numlist))
# 55199224
print(id(num1))
# 55200384

이렇게 [:]를 이용해서 복사하면 된다. [:]는 리스트 슬라이싱을 할 때 쓰는데, 자를 부분을 인자로 넣지 않았기 때문에

전체 리스트를 리턴하게 된다.

이제 id() 함수로 메모리 주소를 확인하면, 두 객체는 다른 메모리 주소를 가리키고 있음을 알 수 있다.

댓글