generator는 한 번에 한 개의 항목을 생성(메모리 유지X)
import array
chars = '!@#$%^&*()_+'
tuple_g = (ord(s) for s in chars)
print(tuple_g)
# 결과: <generator object <genexpr> at 0x00000279567B3900>
위에 tuple_g를 찍어 보면 generator object와 id값이 찍히는데요.
이는 대조적으로 그동안 리스트 컴프리헨션과 다르게 값을 메모리에 띄워놓은 것이 아니라
줄만 세워놓고 첫번째 값을 대기시켰다고 보면 되요.
예를들어. next()와 for문을 돌려서 순차적으로 하나씩 뽑아보면 값이 잘 나오게되요.
print(next(tuple_g))
# 결과: 33
next()는 generator객체의 값을 한개씩 출력함
for i in tuple_g: print(i)
# 결과:
#33
#64
#35
#36
#37
#94
#38
#42
#40
#41
#95
#43
for문을 이용해 모든 generator 객체의 값을 출력함.
그래서 generator가 어떻다는 것이고, 다른 컨테이너와 flat 자료형과 어떤 차이점이 있을까요.
아래 예제에서 확인 할 수 있는 것이 next() 메소드와 for문을 사용하기 전 까지는 메모리에 띄우지 않는다는점! generator는 실행 시점에 값을 반환하는 것임.
# 방법1
print('ex3-1 -', ('%s' % c + str(n) for c in ['A','B','C','D'] for n in range(1,11)))
# 결과: ex3-1 - <generator object <genexpr> at 0x000001BF54E73970>
# 방법2
for s in ('%s' % c + str(n) for c in ['A','B','C','D'] for n in range(1,11)):
print(s)
# 결과2: A1 ... D10
array_g = array.array('I', (ord(s) for s in chars))
# 결과: array('I', [33, 64, 35, 36, 37, 94, 38, 42, 40, 41, 95, 43])
만약 배열객체에서 안의 리스트 값만 보고싶다면 tolist() 메서드를 이용하면되요.
array_g.tolist()
#결과 : [33, 64, 35, 36, 37, 94, 38, 42, 40, 41, 95, 43]
# list 주의점
marks1 = [['~'] * 3 for n in range(3)]
marks2 = [['~'] * 3] * 3
print('ex4-1 -',marks1, type(marks1))
print('ex4-2 -',marks2, type(marks2))
print()
marks1[0][1] = 'X'
marks2[0][1] = 'X'
print('ex4-3 -',marks1, type(marks1))
print('ex4-4 -',marks2, type(marks2))
아래 결과 값중에 ex4-4의 0,1,2인덱스 값의 [1]인덱스 모두가 동일하게 바껴버렷다.
결과
ex4-1 - [['~', '~', '~'], ['~', '~', '~'], ['~', '~', '~']] <class 'list'>
ex4-2 - [['~', '~', '~'], ['~', '~', '~'], ['~', '~', '~']] <class 'list'>
ex4-3 - [['~', 'X', '~'], ['~', '~', '~'], ['~', '~', '~']] <class 'list'>
ex4-4 - [['~', 'X', '~'], ['~', 'X', '~'], ['~', 'X', '~']] <class 'list'>
증명
print('ex4-5 -',[id(i) for i in marks1])
print('ex4-6 -',[id(i) for i in marks2])
# ex4-5 - [1832207621248, 1832207621184, 1832207621056]
# ex4-6 - [1832207620992, 1832207620992, 1832207620992]