본문 바로가기
관리자

Programming-[Backend]/Python

파이썬 중급 - 3. 시퀀스, 제너레이터, sorted, unpacking, immutable 등

728x90
반응형

시퀀스

시퀀스 기본

https://wikidocs.net/84391

파이썬에는 3가지 시퀀스 자료형이 있다.

  • 문자열 : 문자열(string) ‘Hello’는 문자(character)들의 시퀀스이다.
  • 리스트 : [1, 4, 5]
  • 튜플 : (’GOOD’, 100, 121.12)

모든 시퀀스는 순서가 유지되고, 정수로 인덱싱하며 길이가 있다.

 

 

자료형 구분 정리

컨테이너와 플랫

컨테이너(container): 서로 다른 자료형을 하나의 컬렉션에 담을 수 있는 것([list, tuple, collections.deque])

플랫(Flat): 한 개의 자료형만 담을 수 있는 것([str, bytes, bytearray, array.array, memoryview])

 

가변 vs 불변형

가변형(list, bytearray, array.array, memoryview, deque)

불변형(tuple, str, bytes)

 

 

참고 : ord, chr, map 함수

ord 함수와 chr함수

ord 함수는 char형을 받아와서 unicode값을 반환한다. chr 함수는 이와 반대로 유니코드 값을 받아와서 문자로 변경해준다.

파이썬 map 함수

첫 번째 인자는 함수이고, 두번째 인자는 반복할 수 있는 자료형(리스트, 튜플 등)이 온다. 두번째 인자로 들어온 반복 자료형의 원소를 하나씩 첫 번째 인자의 함수에 넣어서 실행하는 방식으로 작동한다.

map 함수의 반환값은 map 객체이기 때문에 list, tuple 등으로 변환시켜주는 것이 편하다.

import math  # math.ceil 함수 사용

# 예제1) 리스트의 값을 정수 타입으로 변환
result1 = list(map(int, [1.1, 2.2, 3.3, 4.4, 5.5]))
print(f'map(int, 리스트) : {result1}')

# 예제2) 리스트 값 제곱
def func_pow(x):
    return pow(x, 5)  # x 의 5 제곱을 반환

result2 = list(map(func_pow, [1, 2, 3, 4, 5]))
print(f'map(func_pow, 리스트) : {result2}')

# 예제3) 리스트 값 소수점 올림
result3 = list(map(math.ceil, [1.1, 2.2, 3.3, 4.4, 5.5, 6.6]))
print(f'map(func_ceil, 리스트) : {result3}')

 


 

Generator

제너레이터는 시퀀스를 생성해주는 함수이다. 한 번에 한 개의 항목만 생성하여 메모리에 유지가 되지 않기 때문에 성능면에서 단순한 반복문보다 효율적이다. 예를 들어 [1, …, 1000000]의 리스트의 각 원소에 숫자를 1씩 더하기 위해서는 일단 이 리스트를 변수로 선언하고 for문을 사용해야한다. 이렇게 되면 리스트의 모든 원소를 갖는 변수가 메모리에 저장되므로 리스트의 크기만큼 메모리의 공간을 차지하게 되어 낭비가 발생한다. 하지만 generator는 연산이 필요한 그 순간의 데이터만 저장하기 때문에 메모리 낭비가 적다.

iter : 어떤 자료형, 예를 들어 list에 dir(list)로 조회했을 때, __iter__가 존재하면 해당 자료형은 iterator를 갖고 있어서 반복이 가능하다는 것을 뜻한다.

제너레이터의 생성은 list comprehension 구문을 소괄호()로 감싸주는 것으로 가능하다.

list = [ord(s) for s in chars] #list comprehension
tuple_g = (ord(s) for s in chars) #generator

type(tuple_g) # <class 'generator'>
next(tuple_g) # 43 (맨 처음 값) 

예제

print(('%s' %c + str(n) for c in ['A', 'B', 'C', 'D'] for n in range(1,21)))
#<generator object <genexpr> at 0x00012....

for s in ('%s' %c + str(n) for c in ['A', 'B', 'C', 'D'] for n in range(1,21)):
	print(s)
"""
A1
A2
...
D20
"""

array

array는 자유롭게 변경될 수 있는 list에 비해서 크기가 고정되고, 원소의 타입도 고정된 정적 타입의 자료형이기 때문에 수치연산이나 고속의 처리가 필요한(numPy 패키지 등) 상황에 사용한다.

array_g = array.array('I', (ord(s) for s in chars))
print(type(array_g)) # <class array.array>
print(array_g.tolist()) #[43, 95, 56, ...]

 


 

깊은 복사와 얕은 복사

for문을 이용하여 list를 반복 생성하면 깊은 복사처럼 각 list의 id 값들이 개별적으로 생성되지만, *로 list를 반복하면 얕은 복사가 실행되어 주소값만 복사하여 각 list가 같은 객체를 바라보게 된다. 중요한 데이터가 이런 방식으로 같은 객체로 복사하면 치명적일 수 있으므로 주의해야한다. 애매할 때는 id() 함수를 이용하여 확인하는 것이 권장된다.

list1 = [['a'] * 3 for _ in range(5)]
list2 = [['a'] * 3] * 4

list1[0][0] = 'b'
list2[0][0] = 'b'

print(list1) # [['b', 'a', 'a'], ['a', 'a', 'a'], ['a', 'a', 'a']]
print(list2) # [['b', 'a', 'a'], ['b', 'a', 'a'], ['b', 'a', 'a']] 

packing과 unpacking

 

unpacking 

(a, b) = (b, a) 도 packing된 튜플을 unpacking한 뒤 다시 packing하는 형태이다.

 

예시 : divmod

첫 번째 인자를 두 번째 인자로 나눈 몫과 나머지를 튜플 형태로 반환한다. 두 개의 인자를 받는데, 하나의 튜플로 전달하고 싶다면 튜플 앞에 *을 붙여서 unpacking이 되도록 해줘야한다. 함수 자체에 *을 써주면 결과값이 unpacking된다.

print(divmod(100, 9)) #(11,1)

print(divmod((100, 9))) #Type error

print(divmod(*(100,9))) #(11,1)

print(*divmod(100, 9)) #11 1 

range packing

x, y, *rest = range(10)
print(x, y, rest) #1 2 [3,4,5,6,7,8,9]

 


 

mutable vs immutable

list는 연산자의 활용에 따라서 주소값이 동일하거나 달라지지만, tuple은 변경이 불가하므로 항상 주소값이 달라진다.

l = (10, 20)
m = [30, 40]

print(l, id(l)) #(10, 20) 1929188125912(id값)
print(m, id(m)) #[30, 40] 1902190521850(id값)

l = l * 2
m = m * 2

print(l, id(l)) #(10, 20, 10, 20) 1251251623547(id값)
print(m, id(m)) #[30, 40, 30, 40] 1251364894589(id값)

l *= 2
m *= 2

print(l, id(l)) #(10, 20, 10, 20, 10, 20, 10, 20) 1924151902122(id값, 새로 지정)
print(m, id(m)) #[30, 40, 30, 40, 30, 40, 30, 40] 1251364894589(id값, 위와 동일)

 


 

sort vs sorted

sorted는 정렬 후 새로운 객체를 반환하고, sort는 기존 객체를 정렬하여 변경한다. sorted 함수의 인자는 차례대로 reversed, key={함수}를 받는다.

 

animals = ['crocodile', 'dog', 'horse', 'sheep', 'tiger', 'giraffe', 'cat']

#sort와 sorted의 문법 차이
#animals.sort()
#sorted(animals, ...)

print(sorted(animals, key=len))
#길이별 오름차순으로 정렬한다.
#['dog', 'cat', 'horse', 'sheep', 'tiger', 'giraffe', 'crocodile']

print(sorted(animals, key=lambda x: x[-1]))
#각 원소의 맨 뒤 알파벳 오름차순으로 정렬한다.
#['crocodile', 'horse', 'giraffe', 'dog', 'sheep', 'tiger', 'cat']

참조

 

1. 인프런 강의 - 우리를 위한 프로그래밍 : 파이썬 중급 (Inflearn Original)

https://www.inflearn.com/course/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%A4%91%EA%B8%89-%EC%9D%B8%ED%94%84%EB%9F%B0-%EC%98%A4%EB%A6%AC%EC%A7%80%EB%84%90/dashboard

728x90
반응형