| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- postgres
- database
- pycharm
- 개발일지
- 파이썬
- 장고
- settings.py
- AWS
- vpc
- subnet
- ec2
- Django
- vue
- 이터널리턴
- django db with ssh tunnel
- psycopg
- 파이참
- 아나콘다
- 챗봇
- Chatbot
- 파이팅
- 오픈빌더
- chartjs-chart-financial
- RDS
- GPT
- 파이선
- SSH Tunnel
- 따라하며 배우는 파이썬과 데이터 과학
- Python
- Today
- Total
우아한 개발계발 블로그
따라하며 배우는 파이썬과 데이터 과학 (7) - 데이터를 리스트와 튜플로 묶어보자 본문
2021.06.20 - [Study/따라하며 배우는 파이썬과 데이터 과학] - 따라하며 배우는 파이썬과 데이터 과학 (6) - 함수로 일처리를 짜임새있게 하자
따라하며 배우는 파이썬과 데이터 과학 (6) - 함수로 일처리를 짜임새있게 하자
2021.05.31 - [Study/따라하며 배우는 파이썬과 데이터 과학] - 따라하며 배우는 파이썬과 데이터 과학 (5) - 여러 번 반복하는 일을 하자 따라하며 배우는 파이썬과 데이터 과학 (5) - 여러 번 반복하는
w00-ah.tistory.com
이전 글까지 완벽하게 이해했다면 파이썬을 충분히 이해할 수 있는 능력을 갖출 수 있다고 본다.
반복문/조건문, 함수, 다양한 자료형의 변수들을 자유자제로 조합하며 사용할 수 있다면, 스스로 무언가 만들어보면서 공부하는 것이 좋다고 생각한다. 이번장에서는 변수 파트에서 다룬 리스트와 튜플에 대해 간단하게 자세히 다뤄 볼 것이다.
앞서 순서형 자료형인 리스트(list)와 매핑형 자료형인 딕셔너리(dictionay)에 대해 알아보았는데 이것들의 공통점은 여러 개의 데이터를 저장하고 처리할 수 있다는 것이다.
그런데 이게 왜 필요할까. 정답은 간단하다. 같은 종류의 데이터들을 각각 변수에 담아 처리하려면, 그 데이터의 개수 만큼 변수를 만들어야할 것이다. 그러한 과정들은 번거롭기도 번거로울 뿐더러, 앞서 강조한 효율성에 어긋난다.
그래서 우리는 c언어 등의 배열과 비슷한 느낌의 자료형을 사용한다.
리스트와 딕셔너리에 대한 정의 방법은 이전글에서 설명하였으니 참고하자
2021.05.28 - [Study/따라하며 배우는 파이썬과 데이터 과학] - 따라하며 배우는 파이썬과 데이터 과학 (2) - 값을 담아 다루어 보자
따라하며 배우는 파이썬과 데이터 과학 (2) - 값을 담아 다루어 보자
2021.05.28 - [Study/따라하며 배우는 파이썬과 데이터 과학] - 따라하며 배우는 파이썬과 데이터 과학 (1) - 파이썬 기초체력 다지기 따라하며 배우는 파이썬과 데이터 과학 (1) - 파이썬 기초체력 다지
w00-ah.tistory.com
7.1 리스트의 생성
numbers1 = [0,1,2,3,4,5,6,7,8,9]
numbers2 = []
numbers2.append(100)
# >>> numbers2
# [100]
numbers3 = list(range(10,20))
# >>> numbers3
# [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
# []를 쓴다고 list로 형변환이 되는 것이 아님에 주의하자
numbers4 = [range(10,20)]
# >>> numbers4
# [range(10, 20)]
리스트를 생성(정의)할 때는 위와 같은 방법으로 생성할 수 있는데, numbers1과 같이 모든 데이터를 하나하나 명시하여 주거나, numbers2 와 같이 데이터를 하나씩 append 메소드를 이용하여 추가하거나 range와 같은 시퀀스 자료형의 경우에는 list()로 형변환하여 list를 만들어줄 수 있다.
7.2 리스트의 연산과 활용
black_pink = ['Jisoo', 'Jennie', 'Lisa', 'Rose']
print('Jennie' in black_pink)
print('Psy' not in black_pink)
print(black_pink[0:2])
print(black_pink[0])
# True
# True
# ['Jisoo', 'Jennie']
# Jisoo
in 예약어를 이용하여 정의된 list에 해당하는 요소(element) 가 존재하는지 Boolean 값을 통해 알 수 있다.
그리고 반대로 해당하는 값이 존재하지 않는지 확인하고 싶다면 not in 예약어를 이용하여 알 수 있다.
7.2.1 인덱싱 & 슬라이싱
그리고 리스트는 인덱싱과 슬라이싱이 가능한 자료형이므로 위와 같이 활용할 수 있다.
>>> alphabet = ['a','b','c','d']
>>> alphabet[0]
'a'
>>> alphabet[1]
'b'
>>> alphabet[3:4]
['d']
인덱싱과 슬라이싱에서 주의할 것은 인덱싱을하면 요소가 반환되지만, 슬라이싱을 하면 리스트를 자른 것에 불과하기 때문에 반환되는 요소가 하나일지라도 리스트로 반환된다. 돌덩이 깨뜨려~ 돌덩이~ (?)
7.2.2 합연산
>>> nums1 = [1,2,3]
>>> nums2 = [4,5,6]
>>> nums1 + nums2
[1, 2, 3, 4, 5, 6]
>>> nums2 + nums1
[4, 5, 6, 1, 2, 3]
그리고 리스트를 +로 합연산을 해보면 위와 같이 리스트가 합쳐지는 것을 볼 수 있다. 리스트 내부의 값은 정렬되지 않고 더한 순서대로 요소의 인덱스가 정해지니 염두해두자.
>>> nums1 * 4
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
리스트를 * 로 곱연산을 하면 위와 같이 리스트가 반복된다. 어찌보면 당연한 결과이다. 곱한 것이니 덧셈을 반복한 것과 같은 결과를 낳는다.
아래의 내장함수들은 리스트 뿐만아니라 대부분의 순차형, 매핑형 자료형 등에 사용할 수 있으니, 알아두어 활용하도록 하자. 괄호안에 데이터를 넣으면 그에 응하는 결과값을 반환해준다.
| type( ) | 자료형을 반환 |
| len( ) | 길이를 반환 |
| max( ) | 요소들중 최댓값 반환 |
| min( ) | 요소들중 최솟값 반환 |
| sum( ) | 요소들의 합 반환 |
| any( ) | 요소들중 0이 아닌 값이 하나라도 있으면 참을 반환 |
| all( ) | 요소들중 0인 값이 하나라도 있으면 거짓을 반환 |
| sorted( ) | 요소들을 오름차순으로 정렬하여 반환 |
-
| 메소드 | 하는일 |
| index(element) | element가 나타나는 첫번째 인덱스를 반환한다. |
| append(element) | element를 리스트의 마지막에 추가한다. |
| count(element) | 리스트의 요소들 중 element의 개수를 반환한다. |
| extend(list) | 인자로 입력받은 list를 기존 리스트에 삽입한다. |
| insert(index, element) | index 위치에 element를 추가한다. |
| remove(element) | element 원소를 리스트에서 삭제한다. |
| pop(index) | index 위치의 원소를 삭제한 후 반환한다. 이때 index는 생략될 수 있으며 이 경우 리스트의 마지막 원소를 삭제하고 이를 반환한다. |
| sort() | 리스트를 오름차순으로 정렬한다. 인자로 reverse=True를 넘겨주면 내림차순으로 정렬한다. |
| reverse() | 리스트를 현재 상태의 역순으로 뒤집어 준다. |
| find(element) | 원소 element를 찾아서 그 위치를 반환한다. |
>>> n = list(range(10))
>>> n
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> n.append(10)
>>> n
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> n.remove(5)
>>> n
[0, 1, 2, 3, 4, 6, 7, 8, 9, 10]
>>> alphabet = ['a','b','c','d']
>>> alphabet.pop(1)
'b'
>>> alphabet
['a', 'c', 'd']
# 인터프리터에서는 값이 반환되면 출력되기 때문에 1번 인덱스의 'b' 요소가 출력되는 모습을 볼 수 있다.
>>> del alphabet[2] # 인덱싱을 이용하여 삭제
>>> alphabet
['a', 'c']
del 은 list의 메소드가 아니라, 파이썬 자체의 내장함수이기 때문에 오해하면 안된다.
append가 랑 pop가 있는데 왜 굳이 del을 쓰냐고 묻는다면 가장 먼저 떠오르는 것은 범위를 지정해 삭제할 수 있다는 것이다.
앞서 말한 슬라이싱 기능을 이용해 아래처럼 범위를 지정하여 삭제할 수 있다.
>>> alphabet
['a', 'b', 'c', 'd']
>>> del alphabet[1:4:2]
>>> alphabet
['a', 'c']
이정도는 영어를 해석하는 그대로의 작업을 수행해주기 때문에, 외우는데 어려움이 없다.
요즘 IDE에서는 메소드들의 기능을 설명해주니 그것을 읽어보며 사용하는 것도 좋다. 못외워도 쓰다보면 외워진다.
7.3 리스트의 참조
우리가 새로운 리스트를 만들면 파이썬은 메모리에 리스트(요소들)를 저장하고 이를 변수에 저장하면 리스트의 모든 요소를 저장하는 것이 아닌 리스트의 메모리 주소만을 저장한다. 이걸 뜬금없이 왜 알아야하냐면 우리가 나중에 리스트를 복사할 때 문제가 될 수 있기 때문이다.

이렇게 실제 객체는 메모리 상에 존재하고 객체가 존재하는 위치 주소를 가리키는 것을 참조(reference)라고 한다.
그래서 우리가 만약 A 리스트를 만들고 할당연산자(=)를 이용하여 새로운 변수 B에 저장한다면, 그것은 주소값을 복사한 것이기 때문에, B로 리스트의 요소를 조작하면 A의 요소가 변하는 것을 경험할 수 있다.
>>> A = [1,2,3]
>>> B = A
>>> B.remove(1)
>>> A
[2, 3]
>>> B
[2, 3]
분명 우리는 B에서 remove했지만 A에도 요소가 지워진 것을 볼 수 있다. 이 때문에 두 변수가 같은 메모리 주소를 가르키는지 확인하기 위해 메모리 주소에 대한 정보가 필요할 때가 있는데, 이는 id() 함수를 이용하여 알 수 있다.
id() 함수는 객체를 인자로 입력받아 객체의 고유값(reference)을 반환하는 함수이다. 객체의 고유값(id)는 파이썬이 객체를 구별하기 위해서 부여하는 일련번호이므로 큰 의미는 없다. 주소의 값의 대체이라고 생각하면 될 것 같다.
>>> id(A)
2171364475008
>>> id(B)
2171364475008
위에서 확인할 수 있듯 A와 B의 고유번호가 같다. 이는 같은 위치를 가르키고 있다는 것이고 같은 객체를 참조하고 있다는 것이다. 이를 해결하기 위해서는 할당연산자로 복사하는 것이 아닌 다른 방법을 사용해야한다.
아까 리스트를 생성할 때 사용했던 list() 함수를 기억하는가? 이는 형변환뿐만 아니라 리스트의 값들을 복제하는데에도 쓰인다. 코드로 확인해보자.
>>> A = [1,2,3]
>>> B = list(A)
>>> id(A)
2171364335040
>>> id(B)
2171360132224
>>> B.remove(3)
>>> A
[1, 2, 3]
>>> B
[1, 2]
두 객체의 id가 다른 것을 통해 서로 다른 주소를 가리키는 것을 확인할 수 있다. 서로 다른 주소를 가르키므로 B를 수정해도 A는 바뀌지않은 것도 확인할 수 있다. 이처럼 기존의 list의 영향을 주지않고 요소를 수정하려면 list() 를 이용하여 새로운 리스트로 복제해야한다.
이게 어디 쓰일까 싶기도 하겠지만, 이는 나중에 for 반복문에서 list자료형을 사용할 때, 유용하다. for에 list를 넣고 돌릴 때 list의 내부 요소를 조작할 때, IndexError: list index out range 를 오류가 날 수 있는데 그러한 오류를 해결하는데 도움이 된다.
7.4 리스트 함축
리스트 함축 (list comprehension) 이란 수학에서 집합을 정의하는 것과 유사하게 리스트를 표현/정의하는 것을 말한다.
수학에서 자연수의 제곱의 집합은 다음과 같은 수식으로 나타낼 수 있다. { 𝒳 | 𝒳 ∈ ℕ} (ℕ은 자연수 집합)
]이를 바로 리스트 함축으로 표현해보자
>>> [x**2 for x in range(1,10)]
[1, 4, 9, 16, 25, 36, 49, 64, 81]
이게 얼마냐 편하냐면 아래와 같이 3 줄에 걸쳐야할 과정을 한줄의 코드로 줄일 수 있다는 것이다. 이게 혁신이다.
>>> s = []
>>> for x in range(1,10):
... s.append(x**2)
>>> s
[1, 4, 9, 16, 25, 36, 49, 64, 81]
실로 놀랍다.
람다함수를 사용할 수 도 있겠지만 그래도 이게 더 간단하다.
리스트 내부 요소들 각각에 연산을 하거나 함수를 적용시키고 싶으면 numpy나 map 함수를 사용하는 방법이 있겠지만,
이 방법도 좋다.
이 표현에는 조건식을 더하여 처리할 수 도 있다.
>>> [x**2 for x in range(1,50) if x%7==0]
[49, 196, 441, 784, 1225, 1764, 2401]
1~50 까지의 자연수 중에서 7로 나누어 떨어지는 수들의 제곱들을 리스트로 나타낸 것이다.
이것도 반복문과 조건문만 이용한다면 못해도 6줄은 될 것이다.
7.5 튜플
변수 파트에서 리스트와 같이 나왔던 튜플은 앞서 설명했듯이 immutable(불변속성)의 데이터 형이다.
한번 정해진 요소들은 추가하거나 제거, 수정할 수 없다.
왜쓰냐 싶겠지만, 데이터 구조가 한번 정해지면 수정이 불가하므로 구조가 단순하여 리스트에 비해 데이터에 접근하는 속도가 빠르다. 그러므로 튜플과 리스트는 항상 말하듯 적재적소에 효율성을 생각하여 활용해야한다.
대표적인 불변속성 자료형은 - 수치(int, float), 문자열(string), 튜플(tuple) 자료형 이있고
대표적인 가변속성 자료형은 - 리스트(list), 집합(set), 딕셔너리(dictionary) 자료형이 있다.
튜플의 연산은 리스트와 다를 것이 없다. 튜플도 시퀀스의 일종이기 때문에 인덱싱, 슬라이싱이 가능하고, 결합 연산자인 +, * 도 사용가능하고 리스트와 자료형만 다르고 출력 결과는 같다.
7.6 객체지향 프로그래밍? 클래스? 인스턴스? 객체?
소프트웨어 엔지닌어들이 수십 년간 다양한 방법으로 프로그래밍을 하며 개발부터 유지, 보수까지 용이한 프로그래밍 방식이 무엇인가에대해 연구하다가 현재 그중 가장 뛰어난 해결책으로 인정받고있는 방법이 바로 객체지향 프로그래밍 (Object Oriented Programming) 방식이다.
객체지향 프로그래밍은 다야한 객체를 클래스(Class)로 미리 정의해두고 정의된 객체들이 프로그램 상에서 상호작용하며 작업을 수행하는 프로그래밍 방식이다. 앞서 말했듯 type() 함수를 이용하면 <class 'list '> 를 볼 수 있듯, 모든 자료형들도 전부 클래스이다.
클래스도 객체이지만 이 클래스의 틀을 갖는 '인스턴스(Instance)'라는 객체를 생성해야 프로그램 상에서 상호작용할 준비 상태가 된다.
조금더 이해하기 쉽게 예시를 들자면 클래스는 설계도와 같은 것이고,
메모리라는 자원을 할당하여 클래스라는 설계도에 따라 구현된 구체적인 실체를 인스턴스라고 할 수 있다.
전에 말했듯 파이썬의 모든 것은 '객체' 이다. 객체 각각은 자신들의 클래스 구조를 지키면서 각자 서로 다른 값을 담고 자신들이 사용할 수 있는 메소드(Method)로 운용한다. 메소드는 특정한 클래스에 속한 객체들이 사용할 수 있는 함수들을 해당 클래스의 메소드라고 하는데, 쉽게 말하자면 클래스 내부에 정의된 함수라고 보면된다.
그래서 나중에 공부하다보면 메소드와 함수를 혼용하여 혼동하는 경우가 있는데, 클래스 안에 있으면 메소드이고, 클래스 밖에 있으면 함수라고 생각하면 쉽다.
list를 예로 들자면 list 자체는 객체이고, list가 사용할 수 있는 메소드들은 pop(), index(). find(), sort(), remove() 등이 있는 것이다. 메소드를 호출하는 것은 앞서 해봤듯 객체.메소드( )의 형태로 호추한다
에초에 이러한 개념이 추상적인 개념이라 곧장 이해하기란 어렵다. 당장은 쉽게 이해만 하고있으면 되는 것이다.
'Study > 따라하며 배우는 파이썬과 데이터 과학' 카테고리의 다른 글
| 따라하며 배우는 파이썬과 데이터 과학 (9) - 텍스트를 처리해보자 (0) | 2021.06.20 |
|---|---|
| 따라하며 배우는 파이썬과 데이터 과학 (8) - 연관된 데이터를 딕셔너리로 짝을 짓자 (0) | 2021.06.20 |
| 따라하며 배우는 파이썬과 데이터 과학 (6) - 함수로 일처리를 짜임새있게 하자 (1) | 2021.06.20 |
| 따라하며 배우는 파이썬과 데이터 과학 (5) - 여러 번 반복하는 일을 하자 (0) | 2021.05.31 |
| 따라하며 배우는 파이썬과 데이터 과학 (4) - IF! 조건을 따져 실행해 보자 (0) | 2021.05.30 |