재귀(recursion)란 어떤 함수가 그 내부에서 자기 자신을 다시 호출하는 것을 말합니다. 간단한 예로 1부터 10까지의 합을 구하는 문제를 생각해보죠. 이 문제는 가장 단순하게는 반복을 통해서 해결할 수 있다는 생각이 들겁니다. 1부터 10까지 루프를 돌면서 각 값을 최종 결과에 계속 누적해주면 됩니다. def sample(n): result = 0 for i in range(n): # i = 0, 1, 2, ... , n - 1 이므로 'i + 1'을 누적한다. result += i + 1 return result재귀를 이용해서 구현할 때에는 문제를 조금 다르게 바라볼 필요가 있습니다. 1에서 n까지의 합을 구하는 것을 S(n)이라 표현한다면, S(1) = 1 이다. S(9) = 1..
소켓 서버가 소켓을 listen()하던 중 클라이언트가 접속하면 sock.accept()를 호출하여 connection과 address를 얻게됩니다. 이 때 connection은 접속된 클라이언트와 통신할 수 있는 새로운 소켓으로, 1:1 통신을 가정한 상황에서는 일단 클라이언트가 접속된 후에는 리스닝 소켓에서 accept()가 다시 호출될 수 없는 구조이며, 1:N 통신을 사용하려면 접속 소켓을 통해 데이터를 주고 받는 코드는 별도의 스레드에서 작동해야 합니다. 대신 이러한 구조는 클라이언트가 접속할 때마다 새로운 스레드를 만들게 되고, 상대적으로 비싼 작업이 됩니다. 따라서 간단한 데이터 교환과 같은 경우에는 싱글 스레드 기반에서 다중 접속을 관리하는 것이 (가능하다면) 훨씬 권장되는 방법입니다. 싱..
같은 컴퓨터에서 여러 버전의 파이썬을 사용하거나 virtualenv 가상환경을 사용하는 경우에 Jupyter 노트북에서 특정 버전/환경의 커널을 추가하여 사용할 수 있다. 이 때, 모든 파이썬 버전/환경에서 주피터를 설피할 필요는 없고, 필요한 파이썬에 대해서 커널만 설치하면 된다. 커널만 추가로 설치하려는 경우에는 ipykernel 패키지를 사용한다. # ipykernel 설치 (venv)> pip install ipykernel ... # 커널 설치 (venv)> python -m ipykernel install --name py39-venv --display-name "Python 3.9 (venv)" ... # 커널 확인 (venv)> jupyter kernelspec list 이렇게 커널만 설치..
오늘은 지식in 같은 곳에서 가장 쉽게 접하는 질문 중 하나인 윤년을 계산하는 방법에 대해서 이야기해보자. 사실 코드만 써 놓으면 너무 간단하니까 윤년에 대해 몇 가지 이야기를 좀 해보도록 하겠다. 윤년이란 무엇인가? 1년은 지구가 태양을 한 바퀴도는 것을 일수로 표현한 것으로 우리는 통상 1년 = 365일이라고 알고 있다. 아주 엉뚱한 소리는 아닌데, 실제로 우리가 일상에서 쓰는 1년은 '회귀년'으로 춘분점이 동일한 위치로 돌아오는 데까지 걸리는 시간을 의미한다. 이는 엄밀하게는 365.2422일로 365일 하고도 약 5시간가량이 된다. 이 실제 1년이 365일보다 조금 더 긴 이 차이가 누적이 되어 몇 백 년이 지나면 8월이 한 겨울이 되는 등 실제 계절과 달력이 차이나는 문제가 생긴다. 그래서 지금..
어떤 유한한 집합이 주어지고, 여기에서 랜덤하게 중복없이 n개의 원소를 골라내는 작업을 구현해보자. 가장 간단하게 생각한다면 다음과 같은 알고리듬을 생각할 수 있다. 먼저 골라낼 원소를 가리키는 난수값을 발생시킨다. 1의 난수가 가리키는 집합의 원소를 고른다. 이 때 고르게 된 값이 이전에 뽑은 값과 중복되는지를 체크한다. 만약 한 번이라도 뽑았던 값이라면 버리고, 그렇지 않은 경우 결과에 추가한다. 1~3의 과정을 결과 집합의 크기가 n이 될때까지 반복한다. 로또 번호는 1~45 사이의 범위가 될 수 있기 때문에 random.randint(1, 45)를 통해서 랜덤하게 고를 수 있다. from random import randint result = [] while len(result) < 6: a = ..
행과 열로 이루어진 데이터를 다뤄야 하는 가장 흔한 경우는 DB의 조회 결과를 다루거나 CSV 파일을 다룰 때이다. 이 경우에 각각의 행은 필드값들이 연속된 리스트이며, 전체 데이터 테이블은 개별 행(리스트)이 중첩된 2중 리스트 구조를 갖는다. 하지만 이런 케이스들은 모두 "테이블" 형태의 데이터를 다루고 있다. 즉 대부분의 처리는 각 행 혹은 라인에 대해 반복하면서 특정한 작업을 처리한다. 그러다보니 대부분 그리드 형식의 데이터를 다루는 경우에 아무런 거리낌없이 2중 리스트를 사용하고 있는데, 개인적으로 "테이블" 형식의 데이터가 아닌 단순 그리드에 대해서는 2중 리스트를 사용하는 것을 그리 좋아하지 않는다. 이 글에서는 그리드의 데이터를 단일 리스트를 사용하여 다루는 기법에 대해서 알아보겠다. 그리..
리스트에서 중복된 원소를 제거하려고 하는 상황을 가정해보자. 보통은 이런식의 코드를 생각하기 쉽다. def uniq(aList): result = [] for a in aList: if result.count(a) < 1: result.append(a) return result 임시 리스트를 만들고, 원본 리스트의 각 원소를 순회하면서 임시 리스트에 "들어있지 않다면" 추가하는 작업을 반복하여 임시리스트가 중복을 제거한 리스트를 담도록 하는 것이다. 여기서는 '.count()를 통해서 멤버십 테스트를 하는 부분을in` 연산자로 바꾸면 좀 더 좋은 성능을 (그리고 좀 더 깔끔한 코드를) 얻을 수 있다. 또 다른 방법으로는 리스트 축약을 사용하는 방법이 있다. 별도의 임시 리스트를 만들지 않고 i 번째 원소..
표준입력과 input 함수 지난 글에서 파이썬에서 텍스트 파일을 액세스할 때 파일 핸들러를 만들어서 사용한다고 했고, 파일 핸들러는 내부적으로 TextIOWrapper라는 버퍼 객체라고 했다. input() 내장함수 역시 TextIOWrapper를 사용한다. 대신 열리는 것이 디스크 상의 파일이 아니라 쉘이 제공하는 표준입력이다. TextIOWrapper(name="") 과 같은 식으로 만들어지는 버퍼가 있고, 이 버퍼는 표준입력을 파일로 간주하고 한 줄씩 읽은 결과를 리턴한다. 즉 이 말은 우리는 input() 함수 자체가 파일의 readline()과 비슷하게 동작한다는 것인데, 쉘의 입출력 특성을 사용하여, input() 함수만으로 파일을 읽어들이는 것이 가능하다는 점 시사한다.다만 차이가 있다면 파..
- Total
- Today
- Yesterday
- 단어 빈도수
- 반복자
- 복수기준정렬
- ipython-notebook
- jupyter-notebook
- 파이썬
- 정렬기준
- iterable
- leapYear
- dict
- 표준입력
- globals()
- Lambda
- 리눅스
- 파일입출력
- 사전
- mutability
- locals()
- 변경가능
- short_circuit
- 함수형
- python list
- 이중리스트를 사용하지 않기
- 튜플언패킹
- 우분투
- sorted
- 정렬키
- 리스트
- 파이썬노트북
- Python
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |