본문 바로가기

Programming/CxO를 위한 코딩

04-1 리스트(list)

반응형

앞 장의 '기본 문법 익히기'에서, 어떤 약속된 문자에다가 값을 지정하고 그 값을 바꾸면서 사용할 수 있는 것을 본 바 있습니다.

 

변수라는 것이죠.

 

1부터 100까지의 합을 구하는 코드는 아래와 같고, 여기서 'sum'이 변수입니다.

sum = 0
for i in range(1,101,1):
    sum = sum + i

sum 변수가 처음에는 0이었다가 1 -> 3 -> 5 -> ... -> 5050 이렇게 변하게 됩니다.

 

그런데, 여기서 sum이 한 가지 값만 가지는 것이 아니고, 이렇게 변하는 모든 값을 덩어리로 가지고 있으려면 어떻게 해야 할까요?

 

이런 요구를 만족시킬 수 있는 게 리스트(list)입니다. 리스트형 변수를 만들면 이 변수에 여러 개의 값들을 저장할 수 있습니다.

 

이제 이 리스트형 변수를 어떻게 만들고 사용하는지에 대해 알아봅니다.

 

데이터 관련한 기능을 살펴볼 때는 항상 CRUD에 대해서 알아보면 됩니다. Create(생성), Read(읽기), Update(수정), Delete(삭제). 여기서도 이 순서에 맞춰서 설명할 겁니다.

 

     

     

    1. 생성하기

    값들을 이용해서 생성

    짝수=[2,4,6,8]  #변수명을 한글로 해봤습니다. 이게 어색하신 분은 even=[2,4,6,8]로 하면됩니다. 
    print(짝수)

    이미 리스트로 정할 값들을 알고 있다면, 그 값들을 콤마로 구분되게 해서 대괄호 안에 넣으면 됩니다.

     

      변수명 = [ 원소0, 원소1, 원소2, ...]

     


    비어있는 리스트 생성

    짝수=[]

    혹은,

    짝수=list()

    어떤 원소를 넣을지 아직 결정되지 않았다면 비어있는 리스트를 만들고 나중에 값들을 채워 넣을 수 있습니다.

     

    비어있는 리스트를 만들 때는 원소 값 없이 비어있는 대괄호로 지정하거나, 변수명=list()처럼 해도 됩니다.

     


    리스트 만들기 예

    a = [1,2,3]  #숫자만
    b = ['a', 'b', 'c'] #문자만
    c = ["학교", "병원", "할머니"]  #문자열
    d = [1, 2, "안녕" ]  #혼합: C나 Java 언어에서는 이처럼 숫자형과 문자형을 혼합해서 사용 못함
    e = [ [1,2,3], ['a', 'b', 'c'] ]  #리스트를 원소로 할 수도 있음 
    

    위 예처럼 파이썬의 리스트는 어떤 자료형도 품을 수 있어서, 직관적으로 그냥 선언해서 사용하면 됩니다.

     

     

    2. 읽기

    리스트 안의 원소들을 위치를 나타내는 인덱스를 통해서 읽을 수 있습니다. 인덱스의 시작은 0(zero)부터 시작

    짝수 = [2,4,6,8]
    print(짝수[0])  #2
    print(짝수[3]) #8
    
    print(짝수[4]) #IndexError: list index out of range
    
    c = 짝수[0] + 짝수[1] 
    print(c) #6
    

    짝수[0]을 하면 짝수 변수가 가리키는 리스트의 첫 번째 원소를 읽은 겁니다.

     

    짝수 리스트의 전체 길이는 4이기에 제일 마지막 원소는 짝수[3]

     

    만약 리스트의 길이보다 더 큰 인덱스를 주고서 값을 읽으려고 하면, 당연히 에러가 뜹니다.

     


    -1 인덱스를 이용한 읽기

    인덱스로 -1을 사용하면, 리스트의 가장 마지막 원소를 가리키게 됩니다.

    짝수 = [2,4,6,8]
    print(짝수[-1]) #8
    print(짝수[-2]) #6
    

    -1 인덱스는 C나 Java언어에는 없는, 파이썬만이 가지고 있는 특이한 기능으로, 제일 마지막 원소를 꼽 집어서 지정할 수 있기에 편리합니다.

     

    -2 인덱스는 끝에서 두 번째, -3은 끝에서 3번째 원소를 가리킵니다.


    범위를 지정해서 읽기

    리스트 안의 원소를 범위를 지정해서 읽을 수도 있습니다.

    a = [0, 1, 2, 3, 4, 5, 6]
    
    b = a[0:2]  # [0, 1]
    c = a[:2]    # [0, 1]
    d = a[2:6]  # [2,3,4,5]
    e = a[2:-1] # [2,3,4,5,6]
    f = a[2:]   # [2,3,4,5,6]
    
    print(a,b,c,d,e,f)
    

    범위를 지정하는 것은 <시작 번호>:<끝 번호 + 1>

     

    <끝 번호>보다 하나 더 큰 값을 지정하는 것에 주의합니다.

     

    범위를 지정할 때 이렇게 '끝 번호'보다 하나 더 큰 수를 지정하게 하는 것은, 프로그래밍 언어의 관습 같은 겁니다.
    [x : y]라고 하면 이 범위 안에 들어가는 인덱스 번호 i는, x <= i < y가 되고, 이 범위 안에 들어가는 원소의 개수는 (y-x)가 됩니다.

     

    위 예에서, b = a[0:2]를 하면, 인덱스 번호가 0부터 1까지 범위의 값이 b라는 변수에 할당이 됩니다.

     

    0부터 시작되는 인덱스는 생략할 수 있어서 a[0:2]a[:2]로 쓸 수 있습니다.

     

    2부터 시작해서 끝까지의 원소 전부를 선택하려면 a[2:]와 같이 하면 됩니다.

     

    a[2:-1]을 하게 되면 마지막 원소가 선택되지 않습니다. -1 인덱스는 끝 원소를 가리키고, 범위지정 규칙에 의해 이 끝 원소보다 하나 앞선 원소까지만 선택되기 때문입니다.


    for구문에 리스트 사용하기

    리스트 안에 있는 원소들을 하나씩 꺼내어 쓸데는 for를 사용합니다. (이처럼 for리스트를 같이 사용하는 것이 가장 일반적인 리스트 사용법이기에 잘 알아둬야 합니다.)

     

    사용법은 간단합니다.

     

        for <원소에 대한 변수 이름> in <리스트 변수 이름>: 

     

    여기서 <원소에 대한 변수 이름>i 등 아무 이름이나 사용해도 됩니다.

     

    아래는 리스트에 있는 모든 원소를 한 줄씩 프린트하는 코드.

    a = [1, 3, 5, 7]
    for i in a:
      print(i)
    

     

    3. 수정하기

    인덱스 번호를 지정해서 값 수정하기

    a=[0,1,2,3,4]일 때, 첫 번째 원소 값을 5로 바꾸고자 한다면 a[0]=5라고 하면 됩니다.

     


    리스트에 값을 더 추가하기

    리스트에 값을 더 추가하고자 할 때는 appendinsert 메서드를 사용하면 됩니다.

     

    a=[0,1,2,3,4]일 때, a.append(10)을 하게 되면 a의 값이 [0,1,2,3,4,10]이 됩니다. 리스트의 원소 개수가 5개였는데 10이라는 값이 더 추가되어 원소 갯수가 6개가 됩니다. 이 append 메서드에 의해 추가되는 원소는, 리스트의 가장 끝에 들어간다는 데 주의

     

    a=[0,1,2,3,4]일 때, a.insert(1, 10)이라고 하면, a의 값이 [0, 10, 1, 2, 3, 4]로 됩니다.

     

    insert 메서드는 insert(<추가될 위치>, <추가될 값>)의 형태입니다.

     

    따라서, a.insert(1, 10)라고 하면 인덱스 1번 위치에 값 10을 추가로 넣으라는 명령이 되고, 추가됨에 따라 나머지 값들은 위치가 한 칸씩 이동되게 됩니다.

     

    [심층 설명] 메서드(Method)와 함수(Function)

    어떤 작업을 수행해내는 모듈에 대해, 클래스 내부에 정의되어 있는 것은 메서드라고, 클래스와 상관없이 정의되어 사용되는 것을 함수라고 합니다.

    메서드는 어떤 클래스 내부에 정의되어 있는 것이니, 그 클래스의 <인스턴스 이름>.<메서드 이름>과 같이 사용되는 것이고,

    함수는 그냥 <함수 이름>을 통해서 호출됩니다.

    위에서 리스트(list)는 클래스이고, a=[0,1,2,3,4]라고 하는 순간 a라는 이름의 인스턴스가 생성된 것이기에 a.insert(1,10)과 같이 리스트 클래스 내부에 정의되어 있는 insert 메서드를 사용할 수 있었던 것입니다.

     

    리스트를 만들 때, 처음부터 어떤 원소가 들어갈지 결정되어 있다면 a=[1,2,3,4]처럼 만들면 됩니다.

     

    그런데, 구구단의 2단의 값 전체를 리스트로 만들고 싶은 경우와 같이, 어떤 수식을 통해 나온 결괏값을 리스트로 저장하고 싶다면, 다음과 같이 하면 됩니다.

    a=[]
    for i in range(1,10):
        a.append(2*i)
    
    print(a)  # [2, 4, 6, 8, 10, 12, 14, 16, 18]  
    

     

    4. 삭제

    위치 번호를 지정해서 지우기

    a=[0,1,2,3,4]일 때, del a[1]이라고 하면, a의 값이 [0,2,3,4]로 됩니다. 위치 번호 1에 있던 원소가 삭제된 것입니다.

     

    제일 끝에 있는 원소를 지우고자 할 때는 del a[-1]

     

    범위를 지정해서 지울 수도 있습니다. del a[0:2]라고 하면 남아 있게 되는 a는 [2,3,4].


    제일 끝에 있는 원소를 pop 하기

    제일 끝에 있는 값을 튕겨 나오게 하는 것은 pop 메서드를 쓰면 됩니다. 튕겨 나온다는 것은 마지막 원소가 삭제되면서 그 값을 얻어낼 수 있다는 의미입니다.

    a = [0,1,2,3,4]
    b = a.pop()
    
    print(b)  #4  
    print(a)  #[0,1,2,3]
    

     

    이러한 pop 명령은, 컴퓨터 공학에서 중요하게 다루는 '스택'이라는 자료구조에서 쓰이는 명령입니다.

    총의 탄창에 탄약을 하나씩 밀어 넣어서 장전해놓은 게, 하나씩 'pop'되면서 발사되는 것을 상상하면 되는데, 스택이라는 자료구조가 이처럼 어떤 데이터를 하나씩 하나씩 밀어 넣어두고선 'pop'을 통해서 가장 마지막에 집어넣은 자료를 꺼내서 쓰는 겁니다.

    파이썬에서는 이러한 스택 구조를 리스트를 통해서도 사용할 수 있게 이러한 pop 메서드를 제공하는 것입니다.

     

    5. 관련 기능들

    for 루프를 이용한 리스트 단축

    리스트를 사용해서 프로그래밍할 때, 가장 많이 접하게 되는 루틴은, for 구문에서 루프를 돌면서 리스트에 원소를 하나씩 집어넣는 작업입니다. 예를 들어, 구구단의 2단을 리스트에 집어넣는다면,

    이단=[]
    for i in range(1,10):
        이단.append(2 * i)
    
    print(이단)  #[2, 4, 6, 8, 10, 12, 14, 16, 18]

     

    코딩 스타일을 보면, C나 Java언어에서도 위와 유사하게 코딩이 됩니다. 그런데, 파이썬에는 이것을 한 줄로 짤 수 있는 방법이 있습니다.

    이단 = [2 * i for i in range(1,10)]
    
    print(이단)  #[2, 4, 6, 8, 10, 12, 14, 16, 18]
    

    결과는 똑같은데, 한 줄로 for 루프를 돌면서 리스트 값을 넣는 구문이 완료되었습니다!!

     

    이러한 것을 'for 루프를 이용한 리스트 단축'이라고 하고 형태는,

     

       <리스트형 변수 이름> = [ <리스트에 넣을 원소> for <원소 이름> in <튜플 혹은 리스트> ]

     

    하나 더 예를 들어 보겠습니다.

     

    a = [1,3,5,7,9] 일 때, a의 각 원소에 3을 곱한 것들을 리스트로 만드고 싶다면,

    a = [1,3,5,7,9]
    b = [3 * i for i in a]  # [3, 9, 15, 21, 27]
    
    이처럼 여러 줄로 되어 있는 것을 한 줄로 만든 것이, 별거 아닌 것처럼 보이지만, 코드를 굉장히 읽기 쉽게 만듭니다. 물론 익숙하지 않으면 오히려 더 코드가 어렵다고 하는 사람도 있으나, 조금만 익숙해지면 이렇게 한 줄짜리 코딩이 가독성이 더 좋습니다.

     


    리스트 합치기

    + 연산자를 통해서 두 리스트를 합칠 수 있습니다.

    a = [0, 1, 2]
    b = [3, 4, 5, 6]
    c = a + b 
    print(c)  #[0, 1, 2, 3, 4, 5, 6]
    

     


    리스트의 크기 알아내기

    리스트의 크기(원소가 몇 개 있는지)는 len 함수로 알 수 있습니다.

    a = [0, 1, 2]
    print(len(a))  #3
    

    리스트에 있는 원소들을 정렬하기

    리스트 안의 원소들을 큰 순서 혹은 작은 순서로 정렬할 수 있습니다.

    a = [10, 0, 1, 2, 3, -1]
    a.sort()  # [-1, 0, 1, 2, 3, 10]
    print(a)
    
    a.sort(reverse=True)  #내림차순으로 정렬할 때는 이렇게 reverse=True로 하면 됨
    print(a) # [10, 3, 2, 1, 0, -1]
    

     

    6. 연습하기

    연습 문제 1

    1에서부터 100까지 차례차례 더할 때의 값 전부를 리스트로 만드세요.

    즉, 결과 값을 저장할 리스트가 합_리스트라면, 합_리스트=[1, 3, 5, 8, ... , 5050]가 되도록 코딩하고 출력하면 됩니다.

     

    답은, 

    더보기
    합리스트 = []
    합 = 0
    for i in range(1,101):
        합 = 합 + i
        합리스트.append(합)
    
    print(합리스트)
    

    연습 문제 2

    2단~9단까지의 구구단을 구해서 리스트로 만드세요.

    2단~9단까지를 각각 리스트로 만들고, 이 리스트들을 다시 하나의 구구단 리스트에 담고 출력하면 됩니다. 출력 결과는 다음과 같이 되어야합니다.

    [[2, 4, 6, 8, 10, 12, 14, 16, 18], [3, 6, 9, 12, 15, 18, 21, 24, 27], [4, 8, 12, 16, 20, 24, 28, 32, 36], [5, 10, 15, 20, 25, 30, 35, 40, 45], [6, 12, 18, 24, 30, 36, 42, 48, 54], [7, 14, 21, 28, 35, 42, 49, 56, 63], [8, 16, 24, 32, 40, 48, 56, 64, 72], [9, 18, 27, 36, 45, 54, 63, 72, 81]]

    직접 고민해서 프로그래밍을 해보고 난 후, 자신이 만든 코드가 아래 정답 1~6 사이에 어느 코딩에 가까운지 확인하시기 바랍니다. (전부 올바른 정답입니다.)

     

    정답 1

    구구단=[]
    for 단 in range(2,10):
        단_리스트=[]
        for i in range(1,10):
           단_리스트.append(단 * i)
        구구단.append(단_리스트)
    print(구구단)
    

    가장 일반적이고, C나 Java 스타일의 코딩입니다.

     

    2단~9단까지를 for 루프를 이용하고, 그 안에 다시 해당 단의 값을 구하기 위해 for 루프를 사용한 형태입니다.


    정답 2

    구구단=[]
    for 단 in range(2,10):
        단_리스트=[단 * i for i in range(1,10)]
        구구단.append(단_리스트)
    print(구구단)
    

    안쪽에 있는 for 루프를 '단축형 리스트' 표현으로 간단히 한 코드입니다.

     

    2단 3단 등 각 단에 대한 리스트가 단_리스트=[단 * i for i in range(1,10)] 코드 한 줄에 의해서 만들어지는 것이 특징.

     

    만들어진 각 단에 대한 리스트는, 최종 리스트인 구구단에 append 됩니다. 구구단.append(단_리스트)


    정답 3

    구구단=[]
    for 단 in range(2,10):
        구구단.append([단 * i for i in range(1,10)])
    print(구구단)
    

     

    구구단.append를 할 때, append의 파라미터에 '단축형 리스트' 코드를 직접 넣어버린 코드입니다.

     

    이렇게 함으로써 단_리스트라는 변수를 안 써도 되고, 코드가 더 간단해졌습니다.

     


    정답 4

    구구단 = [ [단 * i for i in range(1,10)] for 단 in range(2,10) ]
    print(구구단)
    

    전체 단을 담은 구구단 리스트에 대해서도 '단축형 리스트' 코드로 작성해버려서, 코딩이 한 줄로 끝났습니다.!!

     

    코딩을 하면서 일부러 이렇게까지 단축시킬 필요는 없으나, 익숙해지면 자연스럽게 이렇게 작성이 될 것이고, 최소한 누군가가 이렇게 짜 놓은 코드를 분석할 수준까지는 되어야 합니다.


    정답 5

    def get_gugu(단):
        return [단 * i for i in range(1,10)]
    
    구구단 = [get_gugu(i) for i in range(2,10)]
    print(구구단)
    

     

    프로그램 경험이 많은 사람은 보통 이와 같이 짭니다. 각 단에 대한 리스트를 만들어내는 함수를 만들고, 전체 단에 대한 것은 이 함수를 호출한데 '단축형 리스트' 기법을 써서 한 줄로.

     

    -끝-

     


    다음글: 04-2 딕셔너리(dict)

    목차로 이동: [목차]CxO를 위한 코딩 강좌(파이썬을 중심으로)

    반응형

    'Programming > CxO를 위한 코딩' 카테고리의 다른 글

    04-3 튜플(tuple)  (0) 2020.06.25
    04-2 딕셔너리(dict)  (0) 2020.06.25
    04장. 데이터 다루기  (0) 2020.06.25
    03-3 if 구문 익히기  (0) 2020.06.25
    03-2 함수 만들기  (0) 2020.06.25