Python TIL(4) - Nested Data Structure

random·2021년 3월 22일
0

Python - TIL

목록 보기
4/19

Nested Datastructure 학습 (쥬크박스 만들기)

리스트안에 리스트안에 리스트? 다소 복잡한 자료구조를 탐구해보자!

<튜플이 각 아이템으로 이루어진 리스트 만들어보기>


albums = [("Welcome", "Alice Cooper", 1995),
          ("Bad House", "Bad123", 1922),
          ("Ride the horse", "Farmers", 2009),
          ]

print(len(albums))

for name, artist, year in albums: #아래 방식 말고 이방식이 더 선호됨!
    print("Album: {}, Artist: {}, Year: {}"
    .format(name, artist, year))

for album in albums:  #위에것 보다 비효율적인 방법임
    name, artist ,year = album
    print("Album: {}, Artist: {}, Year: {}"
    .format(name, artist, year))
  • 위 소스코드는 튜플 리스트가 각 아이템으로 포함하고 있는 "albums" 리스트임.
  • 각 아이템 element의 readability를 향상시키기위해 튜플의 언팩킹 특징을 이용, 각각 명시된 키워드로 언팩킹(순서대로, 곡명, 아티스트명, 출시년도) 해줌.
  • 이 때 두가지 방식이 쓰일 수 있는데 아래처럼 불필요한 코드라인을 하나 더 만드는 것보다 위의 코드가 더 효율적인 방법!
  • 중간 print(len(albums))을 통해서 리스트 내 아이템 개수가 3개가 출력됨으로써 데이터 구조가 nested의 특징을 띔을 재확인함.
  • 튜플의 장점: 튜플의 장점: 리스트보다 메모리 덜씀, 용량사용면에서 장점보유. immutable이기 때문에 데이터 보존이 중요한 상황에서 쓰임. 예시) 약사가 쓰는 프로그래밍 시스템

*참고: 리스트도 sequence 타입이기 때문에 unpacking이 가능함 하지만 튜플과 달리 리스트 타입은 아이템이 변경 가능하기 때문에 언팩킹 아이템 숫자가 맞지 않으면 crash됨. 튜플은 언제든지 항상 언팩킹을 성공적으로 실행함. 아이템 변경 불가하니 항상 몇 개 아이템을 언팩할지 알수 있음. 다른 sequence 타입을 언팩킹하것보다 튜플 언팩킹이 따라서 더 통용되는 편임.

  • 위 개념을 확장시켜 아래와 같은 코드로 발전가능해짐.

albums = [
    ("Hit Songs", "Big Bang", 2016,
     [
         (1, "거짓말"),
         (2, "하루하루"),
         (3, "마지막 인사"),
     ]
     ),
    ("Revisited Idol", "Brave Girls", 2017,
     [
         (1, "롤린"),
         (2, "운전만해"),
         (3, "Help Me"),
     ]
     ),
    ("Great Music", "the 1975", 2016,
     [
         (1, "Chocolate"),
         (2, "Sound"),
         (3, "Robbers"),
     ]
     ),
]
  • 위는 다소 복잡하게 들리겠지만 "튜플을 품은 리스트를 품은 튜플을 품은 리스트"의 구조를 띄고 있음. 경우의 수에 맞게 위와 같은 구조가 굉장히 복잡하게 펼쳐질 수 있음.

  • 앨범내 정보 같은 경우는 해당 데이터가 변경될 확률이 극히 적기 때문에 기본 정보 컨테이너로 튜플을 채택함.

  • <sound = albums[2][3][1][1], print(sound)> 의 형태로 내부의 세부 정보를 깊게 탐색하여 선택할 수 있음 = 다중괄호 구조!

  • 위 구조를 nested_datasample.py로 따로 저장후 활용하면 아래의 쥬크 박스형태의 작은 프로그램을 만드는게 가능해짐.


from nested_datasample import albums

SONGS_LIST_INDEX = 3
SONG_TITLE_INDEX = 1

while True:

    print("please choose your album (invalid choice exits): ")
    for index, (title, artist, year, songs) in enumerate(albums):
        print("{}: {}".format(index + 1, (title)))
    
    choice = int(input())
    if 1 <= choice <= len(albums):
        songs_list = albums[choice -1][SONGS_LIST_INDEX]
    else:
        break

    print("Please choose your song: ")
    for index, (track_number, song) in enumerate(songs_list):
        print("{}: {}".format(index +1, song))

    song_choice = int(input())
    if 1 <= song_choice <= len(songs_list):
        title = songs_list[song_choice -1][SONG_TITLE_INDEX]
    else:
        break

    print("-" * 40)
    print("Playing {}".format(title))
    print("-" * 40)
  • 다른 컴터 언어랑 달리 파이썬은 constants가 변하지 않게 하는 특정 장치가 없어서 확실히 구분 짓기 위해 상수 naming시 모두 대문자로 통일하는 관습이 있음.
  • import란에 albums 등 아무 것도 안쓰고 file run 하면 nested_datastructure 전체 파일(내부코드까지 다) 재생시킨다. 만일 해당 파일내에 다른 데이터값이 있었다면 오류가 발생할 것임. 참고할 것!
  • 앨범 내 곡정보 튜플 리스트와 그 내부 정보의 순서를 미리 아니까 index 넘버를 기설정해줌으로써 이하 코딩 시 더 읽기 쉬운 키워드 삽입 가능해짐.
    - <songs_list = albums[choice -1][SONGS_LIST_INDEX]>를 통해서, While 루프가 실행 중일 때 노래정보가 담긴 리스트로 이동함. 그 다음 입력값도 동일한 원리로 최종선택지에 도달하게 됨.
  • enumerate 함수는 index, item 두개의 값이 한 쌍인 결과를 반환하기 때문에, "for index, (title, artist, year, songs)" 에서 "index", "(title...이하 생략)" 한 쌍으로 이루어진 정보가 적혀야 하고, 튜플 내 정보는 그자리에서 바로 언팩킹됨을 의미함.
  • 결과값이 잘 보이도록 "-*40" 을 통해 위 아래 절취선을 만들어줌.

위 소스코드 결과값 예시는 아래와 같음.
input값 = 1, 2

please choose your album (invalid choice exits): 
1: Hit Songs
2: Revisited Idol
3: Great Music
1
Please choose your song: 
1: 거짓말
2: 하루하루
3: 마지막 인사
2
----------------------------------------
Playing 하루하루
----------------------------------------

0개의 댓글