파이썬 복습

2024. 9. 2. 11:43카테고리 없음

1.  문자열 데이터 타입

 

파이썬은 알고리즘에서  문자열 처리에 굉장한 편의성을 가지고 있다.

이를 위해 인덱싱과 슬라이싱, 문자의 합 연산, 반복 연산에 익숙해지는 것이 필요하다.

그리고 문자열, 튜플, 리스트 자료형에서 가변(mutable)과 불변(immutable) 이라는 개념이 있다.

 

이를 이해하기 위해 메모리 주소를 생각해봐야한다.

a = 1
addr1 = id(a)  
a += 1
addr2 = id(a)

print(addr1)
print(addr2)

두 메모리 주소가 다른것을 확인할 수 있다.

 

정수형은 immutable로 메모리에 할당된 데이터를 변경할 수 없다.

초기 1 이 임의의 공간에 배정되고 2가 쓰일 때 1이 배정된 공간에 2를 넣는 것이 아니라 새로운 공간에  2를 넣고 변수 a 가 가리키는 주소를 2를 가리키도록 만든다.

 

문자열 또한 immutable이다. 따라서  str = "love" 라는 변수에 str[1] = "a" 라는 코드로 "lave"를 변경할 수 없다.

위의 숫자처럼 새로운 공간에 "lave"가 생성되고 이미 생성되어있던 "love"는 가비지컬렉터로 제거하는 방식으로 동작할 수 있겠다는 생각을 했다. 하지만 이를 허용한다면 가변, 불변을 모르는 개발자가 사용했을때 메모리 누수가 매우 심해져서 이를 허용하는것이 바람직하게 느껴지진 않았고  또 이렇게 동작시킬거면 불변과 가변을 나누지도 않았을 것 같다는 생각을 했다. 실제 실행결과 str[1] = "a"같은 코드로 str을 변경하려할때 오류가 생기는 것을 확인할  수 있었다.

 

리스트의 경우 가변이여서 list[1] = "a" 같은 코드로 이미 있던 데이터를 변경할 수 있다. 그리고 파이썬의 리스트의 경우 여러 자료형이 혼합되어 들어갈 수 있다.

 

2. 깊은 복사, 옅은 복사

 

파이썬으로 알고리즘을 하다보면 다른 변수에 리스트를 복사하려는데 참조 주소가 같아 복사한곳에 데이터를 변경할 때 원본 데이터도 같이 변경되는 상황이 생긴다. 이는 리스트가 가변(mutable)이여서 옅은복사가 되어 생기는 일이다.

 

a = 1
b = a

print(id(a))
print(id(b))
print(a is b) # true

b = 0
print(id(a))
print(id(b))
print(a is b) # false

불변의 경우는 기존 할당된 공간에 있는 1을 변경할 수 없어 새롭게 0을 임의의 공간에 두고 b는 0을 가리키도록 한다.

따라서 깊은 복사가 일어난다.

 

그렇다면 리스트는 깊은 복사를 하지 못하는 것인가?

import copy

a = [1,2,3,4]
b = copy.deepcopy(a)

위와 같은 코드로 깊은 복사를 할 수 있다.

a.copy()로도 깊은 복사가 가능하긴한데 이방법으론 이차원 이상 리스트는 깊은 복사가 이루어지지 않는다.

이밖에도 list() 로 생성할때 매개변수로 복사할 리스트를 넣어주는 방법과 리스트 슬라이싱을 활용하는 방법이있다.

 

이차원 이상 리스트는 왜 copy로 깊은복사가 이루어지지 않을까?

리스트 내부의 값이 리스트인 경우 가변이기 때문에 참조로 이들을 기억한다.

list = [[1,2,3,4],[1,2,3,4]] 가 있다면 ,  list[0]와 list[1] 모두 참조로 [1,2,3,4]를 기억하는데 copy를 하면 가장 바깥쪽 리스트는 새로운 공간에 배정되더라도 내부의 참조가 같아 제대로 이루어지지 않는것이다.

이 경우 내부 객체 부터 깊은 복사를 하거나 내부는 불변인 튜플을 이용하여 깊은 복사를 할 수 있다. 

 

그리고 깊은 복사의 경우 속도면에서 리스트 슬라이싱이 가장 빨라 리스트 슬라이싱을 사용하는 것을 권장한다.

list = [[1,2,3,4],[5,6,7,8]]
list2 = [row[:] for row in list]

list = [[[1,2,3]
		,[4,5,6]
        ,[7,8,9]],
        [[1,2,3]
		,[4,5,6]
        ,[7,8,9]]]
 
list2 = [[ 1arr[:] for 1arr in 2arr] for 2arr in list]