[Python] 자료구조 - List Tuple

Wonder_Land🛕·2022년 6월 23일
0

[Python]

목록 보기
10/12
post-thumbnail
  1. List의 생성 및 조작
  2. List 내포(List Comprehension)의 특징
  3. Tuple의 생성 및 조작
  4. Tuple 내포(Tuple Comprehension)의 특징
  5. Q&A
  6. 마치며

  • Sequence형
    : 각 항목들에 대해 순서를 가진 자료구조의 총칭
    ex) List, Tuple, ...

1. List의 생성 및 조작

  • 리스트(List)
    : [] 안에 서로 다른 자료형의 값,로 구분해 하나 이상 저장할 수 있는 컬렉션 자료형
  • 각 element는 0부터 시작하는 index로 접근 가능합니다.

  • 한 번 저장된 element는 변경할 수 있습니다.
    (Tuple에서는 불가능했죠?🤔)

1) List의 생성

lst = [10, 21.5, "파이썬", True]	# 선언 및 생성
print(f"{type(lst)} {lst}")

[Result]
<class 'list'> [10, 21.5, '파이썬', True]


2) List의 조작

  1. List의 항목 접근
  2. List의 기본 연산
  3. List의 항목 추가
  4. List의 항목 변경
  5. List의 항목 제거
  6. List의 항목 확인
  7. List와 for문 (List 객체의 개별 항목 접근법)

에 대해 각각 알아보겠습니다.

(1) List의 항목 접근

(1.1) index를 이용한 접근

각 항목은 index를 이용해 접근 할 수 있습니다.

기본적으로 시작 index는 0,
마지막 index는 (n-1)
입니다.

lst = [10, 20, 30, 40, 50]

print(f"lst[0] => {lst[0]}")	
print(f"lst[4] => {lst[4]}")	

[Result]
lst[0] => 10
lst[4] => 50

(1.2) 상대적 index를 이용한 접근

가장 오른쪽에 있는 index는 -1,
가장 왼쪽에 있는 index는 -n
이 됩니다.

lst = [10, 20, 30, 40, 50]

print(f"lst[-5] => {lst[-5]}")	
print(f"lst[-1] => {lst[-1]}")

[Result]
lst[-5] => 10
lst[-1] => 50

(1.3) 범위를 이용한 접근

index를 지정할 때, :을 이용하여 범위를 지정할 수도 있습니다.

하지만 이 경우, 마지막 범위는 포함되지 않습니다.

lst = [10, 20, 30, 40, 50]

print(f"lst[0:3] => {lst[0:3]}")	# 0, 1, 2

[Result]
lst[0:3] => [10, 20, 30]

(1.4) 항목의 위치 반환

List의 내장함수 index()는,
항목의 index를 반환합니다.

lst = [10, 20, 30, 40, 50]

print(f"lst.index(20) => {lst.index(20)}")

[Result]
lst.index(20) => 1

(1.5) IndexError

만약, 유효한 index가 아니라면, IndexError가 발생하니 주의해 주세요!

lst = [10, 20, 30, 40, 50]

print(f"lst[5] => {lst[5]}")

[Result]
IndexError: list index out of range


(2) List의 기본 연산

(2.1) List의 주소 확인

id()함수는,
주소를 확인할 수 있습니다.

lst1, lst2 = [10, 20, 30], [40, 50]

print(f"lst1 : {hex(id(lst1))} {lst1}")
print(f"lst2 : {hex(id(lst2))} {lst2}")

[Result]
lst1 : 0x1b7994eb200 [10, 20, 30]
lst2 : 0x1b7994e6e40 [40, 50]

(2.2) List의 연결

+연산자를 이용해,
두 항목을 연결한 새로운 List를 만들 수 있습니다.

lst1, lst2 = [10, 20, 30], [40, 50]

print(f"lst1 + lst2 : {lst1 + lst2}")

[Result]
lst1 + lst2 : [10, 20, 30, 40, 50]

(2.3) List의 반복 연결

*연산자를 이용해,
List를 반복적으로 연결하는 새로운 List를 만들 수 있습니다.

lst1, lst2 = [10, 20, 30], [40, 50]

print(f"lst1 * 2 : {lst1 * 2}")

[Result]
lst1 * 2 : [10, 20, 30, 10, 20, 30]


(3) List의 항목 추가

(3.1) append()함수를 이용한 항목 추가

List의 내장함수 append()함수는,
list의 마지막에 항목을 추가합니다.

반환값은 None으로 없습니다.

lst = [10, 20, 30, 40]

lst.append(50)	# 마지막에 '50' 추가
print(f"lst : {lst}")

[Result]
lst : [10, 20, 30, 40, 50]

(3.2) inser()함수를 이용한 항목 추가

List의 내장함수 insert()함수는,
list의 특정 위치에 항목을 추가합니다.

(리스트).insert(특정 index,)
lst = [10, 20, 30, 40]

lst.insert(2,20)
print(f"lst : {lst}")

[Result]
lst : [10, 20, 20, 30, 40]

(3.3) extend()함수를 이용한 항목 추가

List의 내장함수 extend()함수는,
list의 마지막에 또 다른 list의 항목을 추가합니다.

lst = [10, 20, 30, 40]

lst.extend([50, 60])
print(f"lst : {lst}")

[Result]
lst : [10, 20, 30, 40, 50, 60]


(4) List의 항목 변경

(4.1) index를 이용한 변경

각 항목은 index를 이용해 변경 할 수 있습니다.

lst = [10, 20, 30, 40]

lst[3] = 50
print(f"lst : {lst}")

[Result]
lst : [10, 20, 30, 50]

(4.2) 범위를 이용한 변경

index를 지정할 때, :을 이용하여 범위를 지정할 수도 있습니다.

하지만 이 경우, 마지막 범위는 포함되지 않습니다.

lst = [10, 20, 30, 40]

lst[1:3] = [50, 60]
print(f"lst : {lst}")

[Result]
lst : [10, 50, 60, 40]

또한 지정된 범위보다 크거나 작은 List로 변경하면,
원래의 List 크기가 변경됩니다.

lst = [10, 20, 30, 40]

lst[1:3] = [50, 60, 70]	# 범위보다 큰 List로 변경
print(f"lst : {lst}")

[Result]
lst : [10, 50, 60, 70, 40]

이처럼, 전체 List의 크기가 변경되었음을 알 수 있습니다.


(5) List의 항목 제거

(5.1) del 명령어를 이용한 제거

del 명령어를 이용하여,
특정 index의 항목을 제거하거나,
특정 범위의 항목을 제거할 수 있습니다.

lst = [10, 20, 30, 40, 50]

del lst[1]	# 특정 index의 항목 제거
print(f"lst : {lst}")

del lst[1:3]	# 특정 범위의 항목 제거
print(f"lst : {lst}")

[Result]
lst : [10, 30, 40, 50]
lst : [10, 50]

(5.2) pop()함수를 이용한 제거

List의 내장함수인 pop()함수를 통해,
특정 index의 항목을 제거할 수 있습니다.

lst = [10, 20, 30, 40, 50]

lst.pop(1)	# 1번째 index 항목 제거
print(f"lst : {lst}")

[Result]
lst : [10, 30, 40, 50]

(5.3) remove()함수를 이용한 제거

List의 내장함수인 remove()함수를 통해,
특정 값을 가지는 첫번째 항목을 제거할 수 있습니다.

lst = [10, 20, 30, 40, 50]

lst.remove(20)
print(f"lst : {lst}")

[Result]
lst : [10, 30, 40, 50]

(5.4) clear()함수를 이용한 제거

List의 내장함수인 clear()함수를 통해,
해당 List의 모든 항목을 제거할 수 있습니다.

lst = [10, 20, 30, 40, 50]

lst.clear()
print(f"lst : {lst}")

[Result]
lst : []

물론, del명렁어와 범위연산자만 이용해 모든 항목을 제거할 수도 있습니다.

del lst[:]

이렇게용 😉


(6) List의 항목 확인

(6.1) in 명령어를 통한 확인

in 명령어를 통해,
List 객체에 해당 항목이 있는지 확인할 수 있습니다.

lst = [10, 20, 20, 20, 30, 40, 50]

print(f"20 in lst => {20 in lst}")

[Result]
20 in lst => True

반대로 없는지 검사하려면, not in명령어를 사용할 수 있습니다.

(6.2) count() 함수를 통한 항목의 개수 확인

count() 함수룰 통해,
특정 항목의 개수를 확인할 수 있습니다.

lst = [10, 20, 20, 20, 30, 40, 50]

print(f"lst.count(20) => {lst.count(20)}")

[Result]
lst.count(20) => 3

만약, 해당 항목이 없다면 0을 반환합니다.


(7) List와 for문 (List 객체의 개별 항목 접근법)

lst = list(range(0, 11, 2))

for i in lst:
    print(i, end = " ")

print()

for idx, val in enumerate(lst):
    print(f"lst[{idx}] => {val}")

[Result]
0 2 4 6 8 10
lst[0] => 0
lst[1] => 2
lst[2] => 4
lst[3] => 6
lst[4] => 8
lst[5] => 10

for i in lst:를 통해,
List의 항목을 반복해서 변수 i에 저장합니다.

for idx, val in enumerate(lst):를 통해,
List를 enumerateion 객체로 변환하고
index와 값을 반복해서 변수 idx, val에 저장합니다.


2. List 내포(List Comprehension)의 특징

1) List의 내포(List Comprehension)

  • List의 내포(List Comprehension)
    : List의 선언 및 초기화 시 for문과 if문을 한 라인에 작성하는 방법
(리스트) = [(표현식) for (변수) in (iterable 객체)]
(리스트) = [(표현식) for (변수) in (iterable 객체) if (조건식)]


코드를 직관적이고, 실행 속도를 빠르게 해주는 장점이 있습니다.

iterable 자료형(List, Tuple, str, ...)의 경우,
리터럴 안에서 for문을 사용하면 내포 기능을 사용 할 수 있습니다.

다음의 예시를 한 번 보죠.

lst1 = [1, 2, 3, 4, 5]
lst2 = []

print(f"lst1 : {lst1}")

for i in lst1:	# for문을 이용
    lst2.append(i)
print(f"lst2 : {lst2}")

[Result]
lst1 : [1, 2, 3, 4, 5]
lst2 : [1, 2, 3, 4, 5]

for문을 통해 lst1항목에 하나씩 접근해서 append()함수로 lst2에 추가했습니다.

그렇다면 List 내포(List Comprehesion)를 사용해 볼까요?

lst1 = [1, 2, 3, 4, 5]
lst2 = []

print(f"lst1 : {lst1}")

lst2 = [i for i in lst1]	# List Comprehension	
print(f"lst2 : {lst2}")

[Result]
lst1 : [1, 2, 3, 4, 5]
lst2 : [1, 2, 3, 4, 5]

lst2 = [i for i in lst1]를 통해,
lst1을 반복해서 참조하는 변수 i의 값으로 이루어진 lst2를 만들게 됩니다.


2) List 내포의 조건문

List 내포 기능을 사용할 때, 조건을 추가할 수도 있습니다.

아래의 예시는, for문과 if문을 통해 값을 lst2에 전달하고 있습니다.

lst1 = [1, 2, 3, 4, 5]
lst2 = []

print(f"lst1 : {lst1}")

for i in lst1:
    if i % 2 == 1:  # 홀수라면
        lst2.append(i)
print(f"lst2 : {lst2}")

[Result]
lst1 : [1, 2, 3, 4, 5]
lst2 : [1, 3, 5]

그렇다면 List 내포(List Comprehesion)를 사용해 볼까요?

lst1 = [1, 2, 3, 4, 5]
lst2 = []

print(f"lst1 : {lst1}")

lst2 = [i for i in lst1 if i % 2 == 1]	# List Comprehension with condition
print(f"lst2 : {lst2}")

[Result]
lst1 : [1, 2, 3, 4, 5]
lst2 : [1, 3, 5]


3) List 내포의 중첩

List 내포 기능을 사용할 때, 중첩해서도 사용할 수 있습니다.

아래의 예시에서는, 반복 for문과 if문을 사용했습니다.

lst1 = [1, 2, 3, 4]
lst2 = []

for i in lst1:
    if i % 2 == 1:  # 홀수 항목
        for j in lst1:  # 중첩 for문
            if j % 2 == 0:  # 짝수 항목
                lst2.append(i * j)

print(f"lst2 : {lst2}")

[Result]
lst2 : [2, 4, 6, 12]

(1 * 2), (1 * 4), (3 * 2),(3 * 4)의 결과가 반환되었음을 알 수 있습니다.

그렇다면 List 내포(List Comprehesion)를 사용해 볼까요?

lst1 = [1, 2, 3, 4]
lst2 = []

# 중첩 List Comprehension with condition
lst2 = [i * j for i in lst1 if i % 2 == 1
              for j in lst1 if j % 2 == 0]

print(f"lst2 : {lst2}")

[Result]
lst2 : [2, 4, 6, 12]

이처럼 List 내포(List Comprehension)를 사용하면,
for / if문보다 직관적이고, 짧고, 간결하며, 더 빠른 코드를 작성할 수 있습니다.

자주 등장하고 사용할 기능이니 꼭 알고 계셔야 합니다 😊


3. Tuple의 생성 및 조작

  • 튜플(Tuple)
    : () 안에 서로 다른 자료형의 값,로 구분해 하나 이상 저장할 수 있는 컬렉션 자료형
  • 각 element는 0부터 시작하는 index로 접근 가능합니다.

  • 한 번 저장된 element는 변경할 수 없습니다.
    (List는 가능했죠?🤔)

1) Tuple의 생성

tpl = (10, 21.5, "파이썬", True)	# 선언 및 생성
print(f"{type(tpl)} {tpl}")

[Result]
<class 'tuple'> (10, 21.5, '파이썬', True)

2) Tuple의 조작

  1. Tuple의 항목 접근
  2. Tuple의 기본 연산
  3. Tuple의 항목 확인
  4. Tuple과 for문 (Tuple 객체의 개별 항목 접근법)

에 대해 각각 알아보겠습니다.

(참고로, Tuple은 element의 수정이 불가능하므로,
Tuple element에 대한 추가, 변경, 제거는 불가능합니다.)

(1) Tuple 의 항목 접근

(1.1) index를 이용한 접근

각 항목은 index를 이용해 접근 할 수 있습니다.

기본적으로 시작 index는 0,
마지막 index는 (n-1)
입니다.

tpl = (10, 20, 30, 40, 50)

print(f"tpl[0] => {tpl[0]}")
print(f"tpl[4] => {tpl[4]}")

[Result]
tpl[0] => 10
tpl[4] => 50

(1.2) 상대적 index를 이용한 접근

가장 오른쪽에 있는 index는 -1,
가장 왼쪽에 있는 index는 -n
이 됩니다.

tpl = (10, 20, 30, 40, 50)

print(f"tpl[-5] => {tpl[-5]}")
print(f"tpl[-1] => {tpl[-1]}")

[Result]
tpl[-5] => 10
tpl[-1] => 50

(1.3) 범위를 이용한 접근

index를 지정할 때,
:을 이용하여 범위를 지정할 수도 있습니다.

하지만 이 경우, 마지막 범위는 포함되지 않습니다.

tpl = (10, 20, 30, 40, 50)

print(f"tpl[0:3] => {tpl[0:3]}")	# 0, 1, 2

[Result]
tpl[0:3] => (10, 20, 30)

(1.4) 항목의 위치 반환

Tuple의 내장함수 index()를 이용하여,
항목의 index를 알 수 있습니다.

tpl = (10, 20, 30, 40, 50)

print(f"tpl.index(20) => {tpl.index(20)}")

[Result]
tpl.index(20) => 1

(1.5) IndexError

만약, 유효한 index가 아니라면, IndexError가 발생하니 주의해 주세요!

tpl = (10, 20, 30, 40, 50)

print(f"tpl[5] => {tpl[5]}")

[Result]
IndexError: tuple index out of range


(2) Tuple의 기본 연산

(2.1) Tuple의 주소 확인

id()함수를 통해,
주소를 확인할 수 있습니다.

tpl1, tpl2 = (10, 20, 30), (40, 50)

print(f"tpl1 : {hex(id(tpl1))} {tpl1}")
print(f"tpl2 : {hex(id(tpl2))} {tpl2}")

[Result]
tpl1 : 0x173cba400c0 (10, 20, 30)
tpl2 : 0x173cb706180 (40, 50)

(2.2) Tuple의 연결

+연산자를 이용해,
두 항목을 연결한 새로운 Tuple을 만들 수 있습니다.

tpl1, tpl2 = (10, 20, 30), (40, 50)

print(f"tpl1 + tpl2 : {tpl1 + tpl2}")

[Result]
tpl1 + tpl2 : (10, 20, 30, 40, 50)

(2.3) Tuple의 반복 연결

*연산자를 이용해,
Tuple을 반복적으로 연결하는 새로운 Tuple을 만들 수 있습니다.

tpl1, tpl2 = (10, 20, 30), (40, 50)

print(f"tpl1 * 2 : {tpl1 * 2}")

[Result]
tpl1 * 2 : (10, 20, 30, 10, 20, 30)


(3) Tuple의 항목 확인

(3.1) in 명령어를 통한 확인

in 명령어를 통해,
Tuple 객체에 해당 항목이 있는지 확인할 수 있습니다.

tpl = (10, 20, 20, 20, 30, 40, 50)

print(f"20 in tpl => {20 in tpl}")

[Result]
20 in tpl => True

반대로 없는지 검사하려면, not in명령어를 사용할 수 있습니다.

(3.2) count() 함수를 통한 항목의 개수 확인

count() 함수룰 통해,
특정 항목의 개수를 확인할 수 있습니다.

tpl = (10, 20, 20, 20, 30, 40, 50)

print(f"tpl.count(20) => {tpl.count(20)}")

[Result]
tpl.count(20) => 3

만약, 해당 항목이 없다면 0을 반환합니다.


(4) Tuple과 for문 (Tuple 객체의 개별 항목 접근법)

tpl = tuple(range(0, 11, 2))

for i in tpl:
    print(i, end = " ")

print()

for idx, val in enumerate(tpl):
    print(f"tpl[{idx}] => {val}")

[Result]
0 2 4 6 8 10
tpl[0] => 0
tpl[1] => 2
tpl[2] => 4
tpl[3] => 6
tpl[4] => 8
tpl[5] => 10

for i in tpl:를 통해,
tuple의 항목을 반복해서 변수 i에 저장합니다.

for idx, val in enumerate(tpl):를 통해,
tuple을 enumerateion 객체로 변환하고
index와 값을 반복해서 변수 idx, val에 저장합니다.


4. Tuple 내포(Tuple Comprehension)의 특징

1) Tuple의 내포(Tuple Comprehension)

  • Tuple의 내포(Tuple Comprehension)
    : for문과 if문을 한 라인에 작성하는 방법
(튜플) = [(표현식) for (변수) in (iterable 객체)]
(튜플) = [(표현식) for (변수) in (iterable 객체) if (조건식)]


코드를 직관적이고, 실행 속도를 빠르게 해주는 장점이 있습니다.

iterable 자료형(List, Tuple, str, ...)의 경우,
리터럴 안에서 for문을 사용하면 내포 기능을 사용 할 수 있습니다.

Tuple 내포(Tuple Comprehesion)를 사용해 볼까요?

tpl1 = (1, 2, 3, 4, 5)
print(f"tpl1 : {tpl1}")

tpl_generator = (i for i in tpl1)	# Tuple Comprehension을 통해 generator 객체 생성
tpl2 = tuple(tpl_generator)	  # generator 객체를 tuple 객체로 변환
print(f"tpl2 : {tpl2}")

[Result]
tpl1 : (1, 2, 3, 4, 5)
tpl2 : (1, 2, 3, 4, 5)

generator = (i for i in tpl1)를 통해,
Tuple Comprehesion을 사용하여 generator 객체가 생성되었습니다.

그리고 생성된 generator 객체를 tuple()함수를 사용하면,
실제 데이터 항목을 가진 Tuple 객체 tpl2가 생성됩니다.


2) Tuple 내포의 조건문

Tuple 내포 기능을 사용할 때, 조건을 추가할 수도 있습니다.

tpl1 = (1, 2, 3, 4, 5)
print(f"tpl1 : {tpl1}")

tpl2 = tuple(i for i in tpl1 if i % 2 == 1)	# Tuple Comprehension with condition
print(f"tpl2 : {tpl2}")

[Result]
tpl1 : (1, 2, 3, 4, 5)
tpl2 : (1, 3, 5)


3) Tuple 내포의 중첩

Tuple 내포 기능을 사용할 때, 중첩해서도 사용할 수 있습니다.

tpl1 = (1, 2, 3, 4)

# 중첩 Tuple Comprehension with condition
tpl2 = tuple(i * j for i in tpl1 if i % 2 == 1
                   for j in tpl1 if j % 2 == 0)

print(f"tpl2 : {tpl2}")

[Result]
tpl2 : (2, 4, 6, 12)

(1 * 2), (1 * 4), (3 * 2),(3 * 4)의 결과가 반환되었음을 알 수 있습니다.

이처럼 Tuple 내포(Tuple Comprehension)를 사용하면,
for / if문보다 직관적이고, 짧고, 간결하며, 더 빠른 코드를 작성할 수 있습니다.


5. Q&A

-


6. 마치며

오늘은 저번에 변수를 다뤘던 글에서 등장했던
List와 Tuple에 대해 자세히 살펴봤습니다.

Iterable하며 Sequence한 Type의 가장 대표적인 자료구조인 List와 Tuple은 정말 다양하게 쓰일 수 있는 구조입니다.

각 자료형의 내장함수 및 활용법을 자세히 알고있는게 좋겠죠?

오늘 배웠던 내용만 잘 기억하고 있어도 웬만한 문제들은 해결할 수 있겠죠...?

그리고 또 다른 내용인 '내포'

사실, 문제를 풀다가 막히거나 다른 답과 비교하려고 구글링을 해보면 대부분 이 내포 기능을 사용하시더라구요.

근데 전 잘 몰랐어요ㅎㅎ 😊
(제가 1학년 때 파이썬을 배울 때도 교수님들이 가르쳐주신 기억이 없어요...)
(역시 컴공 공부는 혼자할 때 진정 빛나는 법이죠 😎)

그래서 이게 뭐지.. 어떻게 쓰는거야..
하면서 그냥 넘겼던 적이 많았거든요..

오늘로서 그럴 일은 없을 것 같네요.

사실 공부하면서 사용해보니까 너무 편한 기능이더라구요
이걸 왜 지금 안건지 😂
이제라도 배웠으니까, 잘 써봐야겠어요..

[Reference] : 위 글은 다음 내용을 참고, 인용하여 만들어졌습니다.

  • 전반적 내용 : 삼성 SW Expert Academy
profile
아무것도 모르는 컴공 학생의 Wonder_Land

0개의 댓글