Insight
1. 튜플 컴프리핸션이라고 무턱대고 ()를 사용하면 안된다.
2. 어레이를 왜 쓰는지 리스트와 어레이 사이에서 고민한다면 어떤 기준점을 잡을지 알게 되었다.
3. 리스트(가변형)를 사용시 연산자로 처리할때 의도치 않게 얕은 복사가 생길 수 있어 값이 한꺼번에 변동될 수 있음을 조심하자.
튜플 컴프리핸션 (지능형 튜플)을 만들어 보자
일반적으로 튜플 컴프리 핸션은 리스트 컴프리 핸션 거의 같다.
하지만 아래와 같은 우를 범할 때가 있다.
# 제너레이터 생성 예제
tuple_ = (i for i in range(10))
print(type(tuple_)) # <class 'generator'> 제너레이터가 나온다?
print(tuple_) # <generator object <genexpr> at 0x7f59a067ead0>
# Generator : 한 번에 한 개의 항목을 생성하므로 메모리에서 데이터를 유지하지 않아도 됨
# 이미 메모리에 변수를 올려 놓은 다른 자료 형보다 빠르다.
print(next(tuple_)) # 0
print(next(tuple_)) # 1
print(next(tuple_)) # 2
Generator : 한 번에 한 개의 항목을 생성하므로 메모리에서 데이터를 유지하지 않아도 된다.
이미 메모리에 변수를 올려 놓은 다른 자료형보다
필요할때만 불러쓰는 제너레이터로 해 놓는 게 더 빠르다.
제너레이터는 뒤에서 더 자세히 다루도록 하겟다.
그래서 튜플 컴프리 핸션을 할려면 아래와 같다.
# 이와 같이 그냥 제너레이터 가 나오므로
# 아래처럼 tuple의 경우 tuple()로 감싸 주어야 한다.
tuple_real = tuple(i for i in range(10))
print(type(tuple_real))
print(tuple_real) # (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
한개의 자료형을 사용할 때는 컨테이너인 튜플,리스트보다 플랫형인 어레이가 더 좋다.
어레이 컴프리헨션 (지능형 어레이)을 써보자.
array('타입코드(예약어자료 형:b, B, u, h, H, i, I, l, L, q, Q, f or d)', (어레이 컴프리헨션 ))
import array
# array('타입코드(예약어자료 형:b, B, u, h, H, i, I, l, L, q, Q, f or d)', (어레이 컴프리헨션 ))
array_ = array.array('I', (i for i in range(10)))
print(array_) # array('I', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(type(array)) # <class 'module'>
print(array_.tolist) # 어레이를 리스트로 자료형 변환 # <built-in method tolist of array.array object at 0x7f58fdca6e30>
List, Array사이 에서 적합한 자료형을 사용하는 방법
리스트의 사용할 때 고려사항 : 컨테이너형(융통성, 다양한 자료형, 범용적 사용)
어레이의 사용할 때 고려사항 : 플랫형(숫자만 사용시) (리스트의 거의 모든 연산 지원)
하지만 리스트를 골랐어도 리스트 컴프리핸션 시 주의할 점이 있다.
아래의 두개는 같아 보일 수 있어도 다르다.
왜냐하면 리스트 자료형 자체가 가변형이니까.
list_com = [['1'] * 3 for n in range(3)] # 내부 깊은 복사
# for문이 1번씩 돌때 마다 새 객체가 생성된다.
# 굳이 증명을 안하더라고 일반 for문에서도 이렇게 동작한다.
list_mul = [['1'] * 3] * 3 # 내부 얕은 복사
# 기존의 ['1','1','1'] 자체를 3번 얕은 복사로 진행된다.
# 그래서 하나의 ['1','1','1']을 [1번째자리, 2번째자리,3번째자리] 각자 자리에서 바라 보는 구조가 된다.
print('first', list_com) # first [['1', '1', '1'], ['1', '1', '1'], ['1', '1', '1']]
print('second', list_mul) # second [['1', '1', '1'], ['1', '1', '1'], ['1', '1', '1']]
# 수정하기
list_com[0][1] = 'X'
list_mul[0][1] = 'X'
print('first', list_com) # first [['1', 'X', '1'], ['1', '1', '1'], ['1', '1', '1']]
# 원하지 않는 값이 변경되었다.
print('second', list_mul) # second [['1', 'X', '1'], ['1', 'X', '1'], ['1', 'X', '1']]
# 아이디값 확인
print('first', [id(i) for i in list_com]) # 새로운 자료 공간을 만들고 값을 넣는다. first [140177547086816, 140177547086736, 140177547086656]
print('second', [id(i) for i in list_mul]) # 기존의 자료 공간을 여러개로 복사한다 second [140177547086576, 140177547086576, 140177547086576]