Python 정리 - 자료구조 및 Python 자료형

Kyung Jae, Cheong·2023년 3월 21일
4
post-thumbnail

자료구조 (Data Structure)

  • 컴퓨터 공학적 관점에서 자료구조를 간단히 정리해보도록 함.

    • 자세히 다루기엔 너무 내용이 방대하고, OOP개념도 배워야하기 때문에 간단하게만 살펴보고 이후 Python의 자료형을 좀 더 자세히 다루어 보도록하겠음
  • 기초라기보단 심화내용에 가깝기 때문에, 입문자는 훑어보는 정도로 읽고 넘어가는 것을 추천함

  • 자료구조란? 데이터를 표현하고 관리하고 처리하기 위한 구조
  • 자료구조의 목적
    • 수 많은 자료(data)의 조직화를 통한 효율적인 저장, 관리
    • 효율적인 메모리 사용
    • 다양한 자료구조가 존재하지만, 모든 목적에 적합한 만능의 단일 자료구조는 없음
    • 삽입, 삭제, 비교, 교환, 검색 등의 자료특성을 고려해 가장 효율적인 자료구조를 선택해야함
  • 자료구조의 분류
    • 선형구조
      • 배열 (array)
        • 가장 일반적인 구조, 컴퓨터과학에서 사용되는 기본적인 용어
        • 배열의 기능은 각각의 변수를 하나의 변수에 여러 개의 인덱스로 묶는 것
          • 즉, 순서가 있어서 인덱싱 및 슬라이싱으로 처리 가능
        • 파이썬에서는 배열을 리스트와 튜플로 구현하고 활용함
      • 연결리스트 (Linked-list)
        • 각 노드가 데이터와 포인터를 가져서 한줄로 연결된 방식으로 데이터를 저장하는 자료구조
        • 파이썬의 리스트는 자료구조의 배열과 연결리스트의 특징을 모두 갖고 있다
      • 스택 (stack)
        • LIFO(Last In First Out)자료구조, 마지막에 입력된 데이터를 먼저 출력함
      • 큐 (queue)
        • FIFO(First In First Out)자료구조, 처음에 입력된 데이터를 먼저 출력함
      • 덱 (deque)
        • front,rear 양쪽으로 삽입 및 삭제가 가능한 자료구조
    • 비선형구조
      • 트리 (tree)
        • 부모 노드의 밑에 여러 자식 노드가 연결되어 있고, 자식 노드가 다시 부모 노드가 되어 각각의 자식 노드가 연결되어 있는 재귀적 형태의 자료구조
        • 노드와 브랜치를 이용해서 사이클을 이루지 않도록 구성한 데이터 구조로 계층적인 구조를 표현할 때 사용
      • 그래프 (graph)
        • 노드와 노드를 연결하는 간선을 하나로 모아 놓은 자료구조

Python 자료형 (Data type)

  • 파이썬에서 다루게되는 자료형과 연산자에 대해 살펴보도록 하겠음

1. 기본 자료형 (Number, String, Boolean)

  • 파이썬의 가장 기초적인 자료형은 숫자형, 문자열, 논리형으로 구분할 수 있음

1-1. Number (숫자형)

  • 정수(integer)와 실수(float)를 주로 사용함
    • 정수형(integer, int) : 소수점을 가지지않은 실수의 집합
      • Python에서는 메모리가 허용되는 한 무한으로 사용할 수 있는 것이 특징
      • int(a)로 변환할 수 있음
    • 실수형(float) : 소수점을 가지는 실수의 집합
      • Python에서는 소수점 17~18번째에서 데이터 손실이 일어나는 것이 특징
      • float(a)로 변환할 수 있음
# 정수형 (int)
a = 12345678901234567890123456789012345678901234567890
print(a)
print(type(a))
'''
12345678901234567890123456789012345678901234567890
<class 'int'>
'''

# 실수형 (float)
a = 0.12345678901234567890123456789012345678901234567890
print(a)
print(type(a))
'''
0.12345678901234568
<class 'float'>
'''

# 정수형으로 변환 (버림으로 처리됨)
a = 123.5
a = int(a)
print(a)
print(type(a))
'''
123
<class 'int'>
'''
# 실수형으로 변환 (소수점이 붙는다!)
a = 123
a = float(a)
print(a)
print(type(a))
'''
123.0
<class 'float'>
'''
  • 숫자형의 산술연산자
    • + : 더하기
    • - : 빼기
    • * : 곱하기
    • ** : 거듭제곱 (뒷 숫자를 분수로 주면 제곱근 계산)
    • / : 나누기
    • // : 몫
    • % : 나머지
# 산술연산자 (덧셈)
num1 = 10
num2 = 20
result = num1 + num2
print(result)
'''
30
'''
  • 숫자형의 복합 연산자 (=와 결합해 연산과 할당을 동시에 실시함)
    • = : 할당 연산자
    • += : 덧셈 후 할당
    • -= : 뺄셈 후 할당
    • *= : 곱셈 후 할당
    • **= : 제곱연산 후 할당
    • /= : 나눈셈 후 할당
    • //= : 몫 연산 후 할당
    • %= : 나머지 연산 후 할당
# 할당연산자를 적용하지 않은 경우
num = 10
num = num + 20
print(num)
'''
30
'''
# 할당연산자를 적용한 경우
num = 10
num += 20
print(num)
'''
30
'''

1-2. String (문자열)

  • 문자들이 연속적으로 저장된 형태
  • 주로 큰따옴표 " 혹은 작은따옴표'로 묶어서 정의함
    • str(a)로 변환시켜 정의할 수도 있음
str1 = '안녕하세요.'
print(str1)
'''
'안녕하세요.'
'''

# 숫자형 -> 문자열 변환
num1 = 3.141592
print(num1)
print(type(num1))

str2 = str(num1)
print(str2)
print(type(str2))
'''
3.141592
<class 'float'>
'3.141592'
<class 'str'>
'''
  • 인덱싱(요소불러오기), 슬라이싱(한꺼번에불러오기) 가능함
    • 앞에서부터 0,1,2,⋯
    • 뒤에서부터 −1,−2,−3,⋯
str1 = '안녕하세요'
print(str1[0])
'''
'안'
'''
print(str1[-1])
'''
'요'
'''
# 0번째 자리부터 2번째 자리 앞까지
print(str1[0:2])
'''
'안녕'
'''
# 0번째 자리부터 -1번째 자리 앞까지
print(str1[0:-1])
'''
'안녕하세'
'''

다양한 문자열 관련 명령어들

  • 대/소문자

    • .upper() : 문자열 전체 대문자화
    • .lower() : 문자열 전체 소문자화
    • .capitalize() : 맨 앞 문자만 대문자화
    # 전체 대문자화
    s = 'hello world'
    print(s.upper())
    '''
    HELLO WORLD
    '''
     # 전체 소문자화
    s = 'HELLO World'
    print(s.lower())
    '''
    hello world
    '''
     # 첫문자 대문자화
    s = 'hello world'
    print(s.capitalize())
    '''
    Hello world
    '''
  • 문자열 끝 제거 (기본값은 공백으로 설정되어있음)

    • .strip() : 양쪽 공백 제거
    • .lstrip() : 왼쪽 공백 제거
    • .rstrip() : 오른쪽 공백 제거
    • .strip('문자열') : 양쪽 특정 문자열 제거
    • .lstrip('문자열') : 왼쪽 문자열 제거
    • .rstrip('문자열') : 오른쪽 문자열 제거
    # 공백 제거
    s = '    hello world    '
    print(f"'{s}'")
    print(f"'{s.strip()}'")
    print(f"'{s.lstrip()}'")
    print(f"'{s.rstrip()}'")
    '''
    '    hello world    '
    'hello world'
    'hello world    '
    '    hello world'
    '''
    
     # 특정 문자열 제거
    s = '....hello world....'
    print(f"'{s}'")
    print(f"'{s.strip('.')}'")
    '''
    '....hello world....'
    'hello world'
    '''
  • 문자열 치환 (수정하기)

    • .replace('input', 'output') : input을 output으로 변환
    s = 'hello world'
    print(s)
    print(s.replace('hello', 'hi'))
    '''
    hello world
    hi world
    '''
  • 문자열 분리

    • .split('@') : @를 기준으로 분리함
      • 분리한 만큼 문자열의 리스트로 반환됨
      • max split으로 분리 횟수 조절 가능
      • 두개의 변수로 각각 할당 할 수도 있음
    # 문자열 분리 (리스트 반환)
    s = 'hello@world'
    print(s)
    s.split('@')
    '''
    hello@world
    ['hello', 'world']
    '''
    
    s = 'hello@world@com'
    print(s)
    print(s.split('@'))
    '''
    hello@world@com
    ['hello', 'world', 'com']
    '''
    
    # 분리 횟수 조절 
    print(s.split('@', maxsplit=1))
    '''
    ['hello', 'world@com']
    '''
    
    # 분리 후 변수별로 할당하기
    s = 'hello@world'
    print(s)
    s1, s2 = s.split('@')
    print(s1)
    print(s2)
    '''
    hello@world
    hello
    world
    '''
  • 문자열 검색

    • .find('@') : @가 먼저 나온 인덱스(위치)를 반환함
    • .count('@') : @가 포함된 횟수를 반환함
    • len(s) : 문자열 s의 길이(문자 갯수)를 반환
    • .startswith('@') : @으로 시작하는지 여부를 반환 (True or False)
    • .endswith('@') : @으로 끝나는지 여부를 반환 (True or False)
    s = 'hello@world@com'
    print(s)
    # find (처음 나온 인덱스 위치)
    print(s.find('@'))
    # count (문자열 포함 횟수)
    print(s.count('@'))
    # len (문자열 길이)
    print(len(s))
    
    '''
    hello@world@com
    5
    2
    15
    '''
    
    # 시작여부 끝여부
    print(s.startswith('hello'))
    print(s.endswith('om'))
    '''
    True
    True
    '''
  • 지정 길이 만큼 문자열 채우기

    • rjust(width, [fillchar]) : 문자열로 지정길이만큼 앞부분을 채움
    • ljust(width, [fillchar]) : 문자열로 지정길이만큼 뒷부분을 채움
    • zfill(width) : 지정길이만큼 0을 채움, 방식은 rjust와 동일
    # rjust
    
    # "002"
    print("2".rjust(3,"0")) 
    # "50000"
    print("50000".rjust(5,"0")) 
    # "00123"
    print("123".rjust(5,"0")) 
    # "aa123"
    print("123".rjust(5,"a"))
    
    '''
    002
    50000
    00123
    aa123
    '''
    
     # ljust
    
    # "002"
    print("2".ljust(3,"0")) 
    # "50000"
    print("50000".ljust(5,"0")) 
    # "00123"
    print("123".ljust(5,"0")) 
    # "aa123"
    print("123".ljust(5,"a"))
    
    '''
    200
    50000
    12300
    123aa
    '''
    
     # zfill
    
    # "002"
    print("2".zfill(3)) 
    # "50000"
    print("50000".zfill(5)) 
    # "00123"
    print("123".zfill(5))
    
    '''
    002
    50000
    00123
    '''
  • 이외에도 문자열을 처리하는 함수는 다양하고, 문자열을 다루는 또 다른 방법으로는 re 모듈을 통한 정규표현식(regex, Regular Expressions)을 이용하여 처리하는 방식도 많이 쓰임 (따로 글을 정리해야할 정도로 양이 많기 때문에 이 글에서는 다루지 않겠음..)

문자열의 특수 표기법들

  • 문자열을 다룰 때 반드시 알아둬야하는 것이 특수 표기법인 Escape, Raw, Format 문자열이 있고, 이 또한 잘 활용한다면 훨씬 효율적인 프로그래밍이 가능해짐
  • Escape String : 특수한 기능을 수행하도록 해주는 문자, 주로 백슬래시(\ 혹은 )를 앞에 붙여서 표현함
    • \n : 줄바꿈 (개행)
    • \t : 탭 (2~4칸 띄우기)
    • \b : 백스페이스
    • \\ : 백슬래시 (\)
    • \' : 작은 따옴표(')
    • \" : 큰 따옴표(")
    • \r : 현재 라인의 시작 위치로 옮기는 역할, 앞의 모든 문자가 제거됨
print('Hi,   Hello')
'''
Hi,   Hello
'''

# \n : 줄바꿈 (개행)
print('Hi,  \n Hello')
'''
Hi,  
 Hello
'''

# \t : 탭 (2~4칸 띄우기)
print('\tHi,  \t Hello')
'''
	Hi,  	 Hello
'''

# \b : 백스페이스
# \\ : 백슬래시 (\)
print('Hi,\b  \\ Hello')
'''
Hi  \ Hello
'''

# \' : 작은 따옴표(')
# \" : 큰 따옴표(")
print('\'Hi\',  \"Hello\"')
'''
'Hi',   "Hello"
'''

# \r : 현재 라인의 시작 위치로 옮기는 역할, 앞의 모든 문자가 제거됨
print('Hi,  \r Hello')
'''
 Hello
'''
  • Raw string : escape 문자를 특수문자로 인식하지 않고 그대로(raw) 출력
    • 백슬래시가 가득해지는 걸 깔끔하게 해줄 수 있음
    • json, html 문서나 파일경로에서 백슬래시를 그대로 쓰기위해 주로 이용함
    • 문자열 앞에 r이나 R을 붙여주면 됨
# 파일 경로 출력하기 (raw string 활용)
print('C:\programs\nayana')
print('C:\\programs\\nayana')
print(R'C:\programs\nayana')

'''
C:\programs
ayana
C:\programs\nayana
C:\programs\nayana
'''
  • Format string : 변수를 {} 안에 담아서 출력하기 편하게 해줌
    • 문자열 앞에 fF를 붙여주면 됨
    • 뒤에 .format()을 이용할수도 있음
# raw string 사용예제
string_1 = "raw stringg\b 출력"
string_2 = r"raw stringg\b 출력"

# format string 사용예제
print("escape : {}".format(string_1))
print(f"raw : {string_2}")

'''
escape : raw string 출력
raw : raw stringg\b 출력
'''
  • 출력 관련 내용은 python 데이터 입출력에 대해서 따로 다룰 예정이고, 지금은 문자열의 활용에 초점을 맞추어서 살펴보시면 될 듯함!

1-3. Boolean (불리언, 논리형)

  • 참, 거짓으로 나타내는 자료형태
    • True 1 : 0이 아닌 값이 존재하는 경우
    • 거짓 False 0 : 0이거나 값이 존재하지 않는 경우
  • .bool()을 통해 논리형으로 변환할 수 있음
flag = True
print(flag)
print(type(flag))

flag = False
print(flag)
print(type(flag))

'''
True
<class 'bool'>
False
<class 'bool'>
'''
# 0 = False, 1 = True
var0 = 0
var1 = 1
flag0 = bool(var0)
flag1 = bool(var1)
print(flag0, flag1)
'''
False True
'''

# 값이 존재하지 않음 = False
flag_0_1 = bool('')
flag_0_2 = bool(None)
flag_0_3 = bool('a'.strip('a'))
flag_0_4 = bool(0.0)
print(flag_0_1, flag_0_2, flag_0_3, flag_0_4)
'''
False False False False
'''

# 0이 아닌 값이 존재하는 경우 = True
flag_1_1 = bool(' ')
flag_1_2 = bool('0') 	# 이때 0은 숫자형의 0을 의미하는 것에 주의
flag_1_3 = bool(''.join('a'))
flag_1_4 = bool(-1)
print(flag_1_1, flag_1_2, flag_1_3, flag_1_4)
'''
True True True True
'''
  • 조건문의 비교 연산자 (True, False로 결과가 반환됨)
    • < : 앞이 뒤보다 작음
    • <= : 앞이 뒤보다 작거나 같음
    • > : 앞이 뒤보다 큼
    • >= : 앞이 뒤보다 크거나 같음
    • == : 앞과 뒤가 같음
    • != : 앞과 뒤가 같지 않음
# 문자의 비교 연산 (ASCII 코드를 통해 비교가 이루어 짐)
cha1 = 'A'
cha2 = 'S'
print(f"'{cha1}' > '{cha2}' : {cha1 > cha2}")
print(f"'{cha1}' < '{cha2}' : {cha1 < cha2}")
'''
'A' > 'S' : False
'A' < 'S' : True
'''

# 문자와 아스키코드 변환
# 문자 -> ASCII [ ord() ]
print(f"'A' -> {ord('A')}")
print(f"'S' -> {ord('S')}")
'''
'A' -> 65
'S' -> 83
'''
# ASCII -> 문자 [ chr() ]
print(f"65 -> {chr(65)}")
print(f"83 -> {chr(83)}")
'''
65 -> A
83 -> S
'''

# 문자열 자체 비교 연산 (같은지 같지 않은지를 연산함)
str1 = 'Hello world'
str2 = 'hello world'
print(f"'{str1}' == '{str2}' : {str1 == str2}")
print(f"'{str1}' != '{str2}' : {str1 != str2}")
'''
'Hello world' == 'hello world' : False
'Hello world' != 'hello world' : True
'''
  • 조건문의 논리 연산자 (True, False로 결과가 반환됨)
    • A and B 혹은 A & B : A와 B 모두 True면 True로 반환 (교집합)
    • A or B 혹은 A | B : A와 B 중 하나라도 True면 True로 반환 (합집합)
    • not A : A가 False면 True로 반환 (여집합)
# and
print(True and True)
print(True and False)
print(False and True)
print(False and False)
'''
True
False
False
False
'''

# or
print(True or True)
print(True or False)
print(False or True)
print(False or False)
'''
True
True
True
False
'''

# not
print(not True)
print(not False)
'''
False
True
'''
  • 특수 논리 연산자
    • A is B : A와 B가 일치하는 경우 True
    • A is not B : A와 B가 일치하지 않는 경우 True
    • A in B : B안에 A가 있는 경우 True
    • A not in B : B안에 A가 없는 경우 True
# is / is not
print(('Hello') is not ('hello'))
print(('Hello') is ('hello'))
'''
True
False
'''

# in / not in
print('h' not in 'hello')
print('o' in 'hello')
'''
False
True
'''

2. 컬렉션 자료형 (Collection)

  • 숫자형,문자열,불리언을 묶어서 처리하고 관리하기 위한 자료형
  • 리스트, 튜플, 딕셔너리, 세트
    • 리스트 : 순서가 있음 -> 인덱싱 및 슬라이싱 가능 / 수정 가능
    • 튜플 : 순서가 있음 -> 인덱싱 및 슬라이싱 가능 / 수정 불가
    • 딕셔너리 : 순서가 없음 / 수정 가능 / python의 해시테이블
    • 세트 : 딕셔너리 형태에서 키값만을 가진 자료형임, 순서가 없음 / 수정 가능 / 집합연산 가능

2-1. List (리스트)

  • 배열과 연결리스트의 특징을 모두 갖는 Python의 자료형
    • 기본적으로 후입선출(LIFO)의 Stack형 자료구조임.
  • 숫자형,문자열,불리언을 하나로 묶어서 관리함
  • 대괄호[]로 정의함
  • 순서가 있으므로 인덱싱과 슬라이싱이 가능함
  • 다른 list를 묶어서 다중리스트를 형성할 수도 있음
  • 수치적 연산은 불가능 (더하면 뒤에 붙여지는 방식)
# 리스트 예시
list1 = [1, 2]
list2 = [1, 2, [3, 4]] # 이중리스트
list3 = [1, 2, [3, 4, [5, 6]]] #삼중리스트
print(type(list1))
'''
<class 'list'>
'''

# 삼중리스트의 인덱싱, 슬라이싱
c = [1, 2, [3, 4, [5, 6]]]
print(c[2][2][0])
print(c[-1][0:2])
'''
5
[3, 4]
'''

# 리스트의 덧셈 (이어붙이기)
list1 = [1, 2]
list2 = [1, 2, [3, 4]] # 이중리스트
print(list1 + list2)
'''
[1, 2, 1, 2, [3, 4]]
'''
# 뺄셈은 불가능
print(list2 - list1)
'''
TypeError: unsupported operand type(s) for -: 'list' and 'list'
'''
  • 리스트의 다양한 메소드들

    • 리스트.append(값) : 리스트 마지막에 값을 추가하는 함수
    • 리스트1.extend(리스트2) - 리스트1 마지막에 리스트2요소 이어 붙이기
    # append와 extend 두 메소드의 차이점에 주의하자
    
    # '리스트' 추가  
    flavors1 = ['Vanilla', 'Chocolate']
    flavors1.append(['Strawberry', 'MintChocolate'])
    print(flavors1)
    '''
    ['Vanilla', 'Chocolate', ['Strawberry', 'MintChocolate']]
    '''
    flavors2 = ['Vanilla', 'Chocolate']
    flavors2.extend(['Strawberry', 'MintChocolate'])
    print(flavors2)
    '''
    ['Vanilla', 'Chocolate', 'Strawberry', 'MintChocolate']
    '''
    
    # '문자열' 추가
    flavors3 = ['Vanilla', 'Chocolate','Strawberry']
    flavors3.append('MintChocolate')
    print(flavors3)
    '''
    ['Vanilla', 'Chocolate', 'Strawberry', 'MintChocolate']
    '''
    flavors4 = ['Vanilla', 'Chocolate','Strawberry']
    flavors4.extend('MintChocolate')
    print(flavors4)
    '''
    ['Vanilla', 'Chocolate', 'Strawberry', 'M', 'i', 'n', 't', 'C', 'h', 'o', 'c', 'o', 'l', 'a', 't', 'e']
    '''
    • len(리스트) : 리스트의 길이를 반환함
    • 리스트.insert(인덱스, 값) : 지정한 위치에 값을 추가
      • a.insert(len(a), x) 는 a.append(x)와 같음
    my_list=[]
    for i in range(1000, 1100):
        if (i%7==0) and (i%5!=0):
            my_list.append(str(i))
    
    print(','.join(my_list))
    '''
    1001,1008,1022,1029,1036,1043,1057,1064,1071,1078,1092,1099
    '''
    
    my_list=[]
    for i in range(1000, 1100):
        if (i%7==0) and (i%5!=0):
            my_list.insert(len(my_list), str(i))
    
    print(','.join(my_list))
    '''
    1001,1008,1022,1029,1036,1043,1057,1064,1071,1078,1092,1099
    '''
    • 리스트.remove(값) : 값을 지정해서 제거함
    • del : 메모리에서 값을 지정해 제거함
    • 리스트.pop() : 맨 뒤 요소부터 하나씩 제거해서 반환하는 함수
    • 리스트.pop(인덱스) : 지정 인덱스값을 제거해서 반환하는 함수
    # remove()
    list = [11, 12, 43, 4, 6]
    list.remove(43)
    print(list)
    '''
    [11, 12, 4, 6]
    '''
    
    # del
    my_list = [1, 2, 3, 4, 5]
    my_list[0] = 99
    print(my_list)
    '''
    [99, 2, 3, 4, 5]
    '''
    del my_list[0]
    print(my_list)
    '''  
    [2, 3, 4, 5]
    '''
    # pop : 맨 뒤 요소부터 하나씩 뺌
    my_list = [1, 2, 3, 4, 5]
    my_list[0] = 99
    print(my_list)
    
    my_list.pop()
    print(my_list)
    
    my_list.pop()
    print(my_list)
    
    my_list.pop()
    print(my_list)
    
    '''
    [99, 2, 3, 4, 5]
    [99, 2, 3, 4]     # pop() = 5
    [99, 2, 3]     # pop() = 4
    [99, 2]     # pop() = 3
    '''
    
     # 인덱스를 지정하면 인덱스 요소를 하나 뺌
    my_list = [1, 2, 3, 4, 5]
    my_list[0] = 99
    print(my_list)
    
    my_list.pop(0)
    print(my_list)
    
    my_list.pop(1)
    print(my_list)
    
    my_list.pop(2)
    print(my_list)
    
    '''
    [99, 2, 3, 4, 5]
    [2, 3, 4, 5]     # pop(0) = 99
    [2, 4, 5]     # pop(1) = 3
    [2, 4]     # pop(2) = 5
    '''
    • 리스트 순서 정렬 함수
      • 리스트.sort() : 리스트형의 메소드임, 원본 값을 직접 수정함, 정렬값을 리턴하지 않음
      • sorted(리스트) : 파이썬 기본함수, 원본 값을 그대로 두고 정렬값을 반환
    # sort()
    list1 = [7, 6, 5, 1, 4]
    print('sort1 : ', list1)
    
    list2 = list1.sort()
    print('--- 정렬 후 ---')
    
    print('sort1 : ', list1)
    print('sort2 : ', list2)
    '''
    sort1 :  [7, 6, 5, 1, 4]
    --- 정렬 후 ---
    sort1 :  [1, 4, 5, 6, 7]
    sort2 :  None			# 정렬값을 리턴하지 않음
    '''
    
    # sorted()
    listed1 = [7, 6, 5, 1, 4]
    print('sort1 : ', listed1)
    
    listed2 = sorted(listed1)
    print('--- 정렬 후 ---')
    
    print('sort1 : ', listed1)
    print('sort2 : ', listed2)
    '''
    sort1 :  [7, 6, 5, 1, 4]
    --- 정렬 후 ---
    sort1 :  [7, 6, 5, 1, 4]	# 원본 리스트는 그대로
    sort2 :  [1, 4, 5, 6, 7]	# 정렬된 리스트를 반환
    '''

2-2. Tuple (튜플)

  • 리스트와 비슷하지만, 요소의 값을 변경하는 것이 불가능한 자료형
    • 요소값을 못바꾸기 때문에 값이 바뀌지 않거나 변경되지 않도록 할때 사용함
    • 주로 결과물의 형태로 튜플이 자주 사용됨
  • 소괄호()나 콤마,로 정의함
    • tuple() 로도 변환할 수 있음
  • 인덱싱과 슬라이싱이 가능
  • 다중 튜플을 형성할수 있음
tuple_1 = (1, 2)
print(type(tuple_1))
'''
<class 'tuple'>
'''

tuple_2 = 1, 2
print(type(tuple_2))
'''
<class 'tuple'>
'''

tuple_3 = tuple([1,2])
print(type(tuple_3))
'''
<class 'tuple'>
'''

tuple_4 = tuple([1, 2, [3, 4, [5, 6]]])
print(tuple_4)
print(type(tuple_4))
'''
(1, 2, [3, 4, [5, 6]])
<class 'tuple'>
'''

# 삼중 튜플
tuple_5 = (1, 2, (3, 4, (5, 6)))
print(tuple_5)
print(type(tuple_5))
'''
(1, 2, (3, 4, (5, 6)))
<class 'tuple'>
'''

2-3. Dictionary (딕셔너리)

  • 키(key)와 값(value)의 대응관계로 정의되는 자료형
  • 순서가 없는 자료형임 (인덱싱,슬라이싱 불가)
  • 중괄호{}로 정의하고, dict()함수로도 정의할 수 있음
  • Key는 고유값으로 수정이 불가함
    • TMI : 컴퓨터 과학의 관점에서 딕셔너리는 해시테이블 자료구조로써 Key 값을 해시함수(Hash Function)를 통과시켜 얻은 해시값에 연결된 메모리주소에 저장된 Value값을 반환하는 형태이므로, Key값을 수정하게 되면 해시값이 바뀌게 되고 따라서 다른 메모리 주소를 가리키게 되므로 저장된 Value값을 불러올 수 없게 됨.
    • TMI : Python에서는 해시 충돌(Collision)을 방지하기 위해 내부적으로 Open Addressing 방식을 통해 충돌을 해결함. 오픈어드레싱은 비어있는 해시 테이블의 공간에 충돌된 값을 할당하는 방식이기 때문에 키(key)와 값(value)의 대응관계로 값을 저장하고 검색할 수 있음
dic = {}
print(type(dic))
'''
<class 'dict'>
'''

# key, value 값 추가하기
dic = {}
dic['key'] = 'value'
print(dic)
'''
{'key': 'value'}
'''

# key값으로 value 반환하기
dic = {"name": "jane", "age": 22, "grade": 'A'}
print(dic["age"])
print(dic.get("name")) # .get(key)
'''
22
jane
'''

# .items()로 key와 value의 튜플 리스트를 반환
dic = {"name": "jane", "age": 22, "grade": 'A'}
print(dic.items())
'''
dict_items([('name', 'jane'), ('age', 22), ('grade', 'A')])
'''

# .keys()로 키의 리스트 반환
print(dic.keys())
'''
dict_keys(['name', 'age', 'grade'])
'''

# .values()로 값의 리스트 반환
print(dic.values())
'''
dict_values(['jane', 22, 'A'])
'''

2-4. Set (집합)

  • 수학의 집합처럼 사용되는 자료형
  • 순서가 없고, 중복을 허용하지 않음
  • 중괄호{}set()함수로 정의함
    • 딕셔너리에서 key값만 가지는 자료형이라 볼 수 있기 때문에, 동일하게 중괄호로 정의가 가능함
  • 교집합, 합집합, 차집합 계산이 가능함
# set
s = {1, 2, 3}
print(type(s))
'''
<class 'set'>
'''

# list -> set
s = set([1,2,3,2])
print(s)
print(type(s))
'''
{1, 2, 3}
<class 'set'>
'''

# tuple -> set
s = set((1,2,3,2))
print(s)
print(type(s))
'''
{1, 2, 3}
<class 'set'>
'''
  • set의 다양한 메소드들

    • .add() : 하나의 값을 추가할 때 사용
    • .update() : 여러개의 값을 한번에 추가할 때 사용
    # 하나의 값을 추가
    s = {1, 10, 100}
    s.add(50)
    print(s)
    '''
    {1, 10, 100, 50}
    '''
    
    # 여러개의 값을 한번에 추가
    s.update([5, 50, 500])
    print(s)
    '''
    {1, 100, 5, 10, 50, 500}
    '''
    • .remove() : 값에 해당하는 원소를 제거하고, 없으면 KeyError 발생함
    • .discard() : 값에 해당하는 원소를 제거하고, 없어도 에러발생하지 않음
    # 값이 있는 경우 (remove)
    s = {1, 100, 5, 10, 50, 500}
    s.remove(100)
    print(s)
    '''
    {1, 5, 10, 50, 500}
    '''  
    # 값이 있는 경우 (discard)
    s.discard(10)
    print(s)
    '''
    {1, 5, 50, 500}
    '''
    
    # 값이 없는 경우 (remove)
    s = {1, 100, 5, 10, 50, 500}
    s.remove(1000)
    '''
    KeyError: 1000
    '''
    # 값이 없는 경우 (discard)
    s = {1, 100, 5, 10, 50, 500}
    s.discard(1000)
    print(s)
    '''
    {1, 100, 5, 10, 50, 500}
    '''
  • set의 연산자

    • | : 합집합
    • & : 교집합
    • - : 차집합
    • ^ : 대칭자집합 (합집합 - 교집합)
    # set 연산자
    set_a = {1,2,3,4,5}
    set_b = {3,4,5,6,7}
    
    # 합집합
    print(set_a | set_b)
    '''
    {1, 2, 3, 4, 5, 6, 7}
    '''
    # 교집합
    print(set_a & set_b)
    '''
    {3, 4, 5}
    '''
    # 차집합
    print(set_a - set_b)
    '''
    {1, 2}
    '''
    # 대칭자집합 (합집합 - 교집합)
    print(set_a ^ set_b)
    '''
    {1, 2, 6, 7}
    '''
  • set의 연산 메소드

    • .union() : 합집합
    • .intersection() : 교집합
    • .difference() : 차집합
    • .symmetric_difference() : 대칭자집합 (합집합 - 교집합)
    # set 연산메소드
    set_a = {1,2,3,4,5}
    set_b = {3,4,5,6,7}
    
    # 합집합
    print(set_a.union(set_b))
    '''
    {1, 2, 3, 4, 5, 6, 7}
    '''
    # 교집합
    print(set_a.intersection(set_b))
    '''
    {3, 4, 5}
    '''
    # 차집합
    print(set_a.difference(set_b))
    '''
    {1, 2}
    '''
    # 대칭자집합 (합집합 - 교집합)
    print(set_a.symmetric_difference(set_b))
    '''
    {1, 2, 6, 7}
    '''

3. 모듈 및 라이브러리용 자료형

  • 특정 모듈 및 라이브러리에서 사용되는 자료형을 정리해보도록 하겠음
  • 데이터사이언스에서 가장 많이 쓰이는 numpy, pandas, tensorflow, pytorch의 자료형에 대해서 간단하게만 다루고자 함

3-1. ndarray (Numpy)

  • 모듈 numpy에서 배열을 나타내는 자료형
  • Numpy 모듈이 행렬 연산에 특화되어있는 모듈인 만큼, 행렬에 대한 표현과 연산이 가능함 (행렬단위의 연산이므로 형태를 잘 맞추어서 연산을 진행해야함)
  • 리스트나 튜플처럼 순서를 가지고 있어서 동일한 방식으로 인덱싱 및 슬라이싱이 가능함
  • 벡터를 표현하고 연산할 수 있는 것이 가장 큰 특징
    • 이러한 특징 때문에 벡터를 기반으로 계산되는 대부분의 모듈, 라이브러리, 프레임워크에서 numpy를 활용하고 있고, 데이터사이언스 분야에서는 매우 중요한 위치를 차지하고 있다고 볼 수 있음

3-2. Series, DataFrame (Pandas)

  • 모듈 pandas에서 사용하는 고성능 자료형
  • 행과 열로 구성되어 있는 것이 특징이며, 하나의 벡터를 표현하는 Series가 column의 형태로 쌓으면 DataFrame(2차원행렬)으로 표현될 수 있음
  • EXCEL처럼 행렬 단위에서 실시할 수 있는 다양한 기능들을 제공하고 있고, 경험적으로는 주로 데이터의 전처리 분야에서 많이 쓰이는 자료형태임
  • Numpy만큼의 중요성을 가지지는 않지만, Numpy보다 더 직관적으로 데이터를 전처리할 수 있기 때문에, pandas 역시도 데이터사이언스 분야에서는 매우 중요한 위치를 차지하고 있다고 볼 수 있음

3-3. Tensor (Tensorflow, Pytorch)

  • 딥러닝 프레임워크 Tensorflow와 Pytorch에서 사용되는 자료형
  • numpy처럼 벡터와 행렬을 표현하는 자료형태이기 때문에, numpy와 tensor는 서로 변환하여 사용이 가능함
    • 다만 tensor의 경우엔 batch size 단위로 묶어서 관리하는 것이 더 수월한 편임
    • 그러나 numpy array를 입력값으로 바로 넣을 수 있는 기능들을 지원하고 있고, 어떠한 경우엔 numpy array로 입력하는 것이 더 효율적인 경우도 있으므로, 어떠한 형태가 더 적합한지를 따질 순 없다고 봄...
  • tensor의 경우 batch size 설정 등 딥러닝 프레임워크에 알맞게 전처리를 실시하는 경우에 주로 이용되기 때문에, 주로 고차원 데이터를 처리하는데에 초점이 맞추어져 있는 자료형이라 볼 수 있음
  • 대표적인 딥러닝 프레임워크인 Tensorflow, Pytorch 모두 Tensor를 기반으로 동작하는 프레임워크이며, 딥러닝 과정을 입문할 때 가장 먼저 배우고 다루게 되는 가장 기본적인 자료형이기 때문에, 딥러닝에 있어선 매우 중요한 자료형임

마무리

  • 이번 글에서는 컴퓨터 과학에서의 자료구조의 종류를 간단하게 알아보았고, Python의 자료형에 대해 많은 내용들을 다루었음
  • 자료구조와 자료형은 다양한 경험들을 통해 다양한 데이터를 다루어보면서 익숙해지는 것이 가장 중요하다 생각하며, 본인도 앞으로 지속적으로 공부를 해야할 듯 함...
  • 다소 부정확하거나 부족한 내용들도 많지만, 앞으로도 공부해가면서 지속적으로 내용들을 업데이트할 예정..
  • 화이팅 !
profile
Machine Learning (AI) Engineer & BackEnd Engineer (Entry)

0개의 댓글

관련 채용 정보