본문 바로가기
언어/Python

[Python 기본 공부정리] 4. 변수(variable)

by 민-Zero 2019. 12. 19.

공부 내용을 정리하는 목적 이므로 참고용으로만 읽어 주시기 바랍니다. 

틀린 부분에 대한 지적은 감사합니다.

1. 변수 생성

파이썬에서 변수 생성은 대입 연산자 = 을 통해 선언 및 정의 가능하다.

문법)

변수명 = 데이터

다른 언어에서는 해당 변수에 저장할 데이터 타입에 맞추어 변수 타입을 지정해야 하지만 파이썬은 저장되는 데이터에 따라 자동으로 데이터 타입을 결정해 주기 때문에 간편하다. 또한 변수명을 만드는 데에 몇 가지 규칙이 있다.

 

[변수명을 정하는 규칙]

1. 알파벳(대소문자 구분), 숫자, _ 를 사용하여 만들 수 있다.

2. 변수명 첫글자에 숫자는 사용 불가능하다.

3. 파이썬에서 사용하는 키워드는 변수명으로 사용 불가능하다.

 

 

2. 변수란?

파이썬에서의 변수는 다른 언어인 C++이나 java와 차이가 존재하는데, 다른 언어처럼 변수를 생성하면 메모리를 할당받아 해당 데이터를 저장하는 것이 아니다. 파이썬에서 변수는 저장하고자 하는 객체를 가리키는 역할이다. 즉, 포인터라고 따로 존재하지는 않지만 포인터처럼 해당 객체의 주소를 저장하고 있다.

 

해당 예시에서 1과 ['a', 10, 23.1] 이라는 데이터를 a와 b라는 변수에 저장하는것 처럼 보이지만 사실은 1의 값을 가지는 정수형과 ['a', 10, 23.1] 값을 가지는 리스트형이 자동으로 메모리에 할당되고 a와 b 변수는 각각의 데이터가 할당된 메모리 주소를 받아 가리키게 된다.

id()라는 내장 함수를 통해 변수가 가리키는 주소를 확인할 수 있다.

 

따라서 변수 자체가 메모리를 할당받아 데이터를 저장하는 것이 아니라 해당 데이터가 할당된 메모리의 주소를 가리키는 역할을 하기 때문에 b 변수에 a 변수를 대입할 경우 하나의 데이터를 두 개의 변수가 동일하게 가리키게 된 것을 확인할 수 있다.

 

따라서 a로 list값을 변경해도 b 또한 같은 데이터를 가리키고 있기 때문에 같은 값을 출력하는 것을 볼 수 있다.

 

3. 값의 복사

해당 역할이 좋은 점도 있겠지만 만약 이전 데이터를 임시로 저장해 두어야 한다면 위와 같은 일반적인 대입으로는 불가능하게 된다. 경우에 따라 값만 복사하여 두 변수가 다른 주소를 가리키게 해야 할 경우도 존재한다.

 

리스트를 가진 변수일 경우 리스트 전체를 포함할 수 있는 [:]를 통해 값을 복사하여 저장할 경우 두 변수가 가리키는 주소가 달라 a의 값의 일부를 변경하여도 b는 변하지 않는 것을 확인할 수 있다. 

 

또 다른 방법으로는 copy 모듈을 사용하는 것이다. 뒤에 정리하겠지만 copy함수를 사용하기 위해 가져와 사용하는 것이다.

 

지금까지 list형에 관해서만 다루어졌는데 그렇다면 정수, 실수, 튜플 등 다른 자료형은? 이란 의문이 생긴다.

 

의문의 해결점은 저장하는 객체가 mutable(생성 후 값을 변경할 수 있는)인지 immutable(생성 후 값이 변할 수 없는)인지를 생각해야 한다. 앞선 예시처럼 할당한 변수의 값 역시 똑같이 수정되는 것은 리스트와 같은 mutable 객체일 때만 해당하며 정수나 문자열과 같은 immutable 객체일 때는 위의 경우가 해당되지 않는다.

 

즉, mutable 객체는 값이 변할 수 있기 때문에 해당 데이터 객체가 저장된 메모리에서 값을 변경하기만 하면 되기 때문에 같은 주소를 할당한 경우 동시에 값이 바뀌게 된다.

immutable 객체일 경우 값이 바뀌지 않기 때문에 변수를 수정하는 것은 새로운 객체를 메모리에 할당해 그 주소를 가리키게 하는 것이다.

 

immutable객체와 mutable 객체의 차이로 객체의 복사에 관해 얕은 복사(shallow copy)깊은 복사(deep copy) 2가지 복사 방법이 존재한다.

 

얕은 복사)

얕은 복사의 경우 리스트 객체는 별도로 생성하고 안의 내용물은 원본과 동일하게 가져가는 복사 방법이다. 즉 리스트라는 [] 껍데기만 별도로 생성하고 내용물은 동일한 곳을 가리키고 있다고 생각하면 된다. 예시를 통해 확인하면

a와 b의 경우 b[0]에 들어있는 1이란 immutable 한 객체를 수정하기 때문에 mutable객체인 리스트라도 앞서 설명한 것처럼 수정된 새로운 리스트 값을 생성해 할당하게 되므로 a의 값과 b의 값이 다르게 된다.

b와 마찬가지로 같은 a의 값을 할당하게 한 c의 경우 리스트 안에 존재하는 다른 mutable 객체인 리스트의 값을 수정하므로 메모리에 할당된 데이터가 수정되기만 한다. 따라서 얕은 복사를 통해 같은 내용을 지니는 a와 c의 변수는 그대로 같은 주소를 가리키게 되므로 동일한 값이 출력된다.

즉, a, b와 a, c의 차이는 얕은 복사의 경우 내용은 동일한 메모리를 가리키므로 앞서 봤던 수정하는 객체가 mutable 인가 immutable인가에 대한 차이로 인한 데이터 수정 방법의 차이다.

 

깊은 복사)

이 mutable 한 객체의 수정의 경우 동일하게 변경되는 문제를 해결하기 위해 깊은 복사를 사용하면 된다. 얕은 복사와는 다르게 객체 자체를 새롭게 생성하고 내용까지 동일하게 생성하여 복사한다. 따라서 어떤 변수를 수정하더라도 둘은 완전히 다른 객체가 되기 때문에 문제가 발생하지 않는다.

사용 방법은 copy 모듈에 있는 deepcopy 함수를 사용하면 된다.

깊은 복사를 사용했기 때문에 어느 한쪽을 수정하여도 다른 쪽에는 아무런 변화가 없음을 확인할 수 있다.

댓글