파이썬(Python) 데이터 크롤링 기초 수업 정리

개발자나 데이터분석가에게 중요한 능력중 하나를 꼽자면 무엇일까.
자신이 진행할 프로젝트의 데이터를 수집하는 능력도 꽤나 중요하지 않을까 싶다.
그러기 위해서는 크롤링을 해야 할 때가 있는데 크롤링이란 HTML(웹페이지)를 그대로 가져와 데이터를 추출하는 행위를 말한다.
그래서 이번 포스트에서는 학원에서 배운 간단한 크롤링에대해 수업 그대로를 정리하려 한다.

사전준비


크롤링을 하기위해 일단 BeautifulSoup 라는 파이썬 라이브러리를 설치해 주어야 한다.
다음 코드를 터미널에 입력해 라이브러리를 설치한다.

1
pip install beautifulsoup4

설치가 완료되었다면 예제 HTML 문서를 하나 만들어주면 준비는 끝난다.

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Crawl This Page</title>
</head>
<body>
<div class="cheshire">
<p>Don't crawl this.</p>
</div>
<div class="elice">
<p>Hello, Python Crawling!</p>
</div>
<div id="main">
<p>I am in main</p>
</div>
</body>
</html>

BeautifulSoup를 사용하여 크롤링

먼저 크롤링을 하기 위해 파이썬 파일을 만들어준다.

1
from bs4 import Beautifulsoup

이후 Beautifulsoup 라이브러리를 import하고 간단한 함수를 만들어 크롤링을 해보자.



HTML 불러오기

1
2
3
4
5
6
def crawling():
soup = BeautifulSoup(open("data/index.html"), "html.parser") # open의 괄호안에 크롤링할 HTML파일의 위치를 입력
print(soup)

if __name__ == "__main__":
crawling()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8"/>
<title>Crawl This Page</title>
</head>
<body>
<div class="cheshire">
<p>Don't crawl this.</p>
</div>
<div class="elice">
<p>Hello, Python Crawling!</p>
</div>
</body>

HTML 파일이 soup에 저장되어 출력된 것을 볼 수 있다.



필요한 태그만 가져오기

하지만 우리는 HTML 전체가 아닌 특정 텍스트, 태그만 필요로 하기 때문에 그것들을 뽑아낼 수 있어야 한다.

1
2
3
4
5
6
def crawling():
soup = BeautifulSoup(open("data/index.html"), "html.parser")
print(soup.find("p"))

if __name__ == "__main__":
crawling()
1
<p>Don't crawl this.</p>

find()함수는 가장 앞쪽의 한 태그만을 가져온다.
이처럼 p태그가 출력되었는데 두가지 의문이 생길 것이다.
‘p태그는 두개인데 왜 한개만 출력되는가?’와 ‘<p></p>없이 텍스트만 추출 할수 없는가?’라는 것이다.
물론 가능하다.
첫번째는 find()함수를 find_all()로 바꾸면 모든 p태그가 출력되고,
두번째는 find()함수 뒤에 .get_text()를 붙여주면 태그가 제외된 텍스트만 출력이 된다.
이외에도 많은 함수가 있고, Beautiful Soup Documentation 에서 찾아볼 수 있다.



class, id로 태그 가져오기

여전히 크롤링이라기엔(기초지만) 부족하다 원하는 태그를 가져올 수는 있으나 태그가 여러개면 같이 가져올 수밖에 없기 때문이다.
그래서 이번에는 각 태그에 주어진 class와 id를 통해 크롤링하는 법에 대해 알아보자.

index.html을 보면 div태그에 각각 class와 id가 있다.
이를통해 크롤링 하는 코드를 보면

1
2
3
4
5
6
def crawling():
soup = BeautifulSoup(open("data/index.html"), "html.parser")
print(soup.find("div", class_ = "elice").find("p").get_test())

if __name__ == "__main__":
crawling()

다음과 같으며 이를 실행하면

1
Hello, Python Crawling!

위와 같이 출력된다.
만약 class가 아닌 id를 지정해서 태그를 찾고싶을 경우 find()함수 내에 class_ = 가 아닌 id = 를 입력하면 된다.
class는 언더바가 붙고 id는 붙지 않는다.

OPEN API를 통해 데이터 가져오기

open API를 통해 데이터를 가져오는 법도 간단히 알아보자.
이 포스팅은 캐글을 기반으로 진행했으며 데이터는 한국도로공사 공공데이터 포털 의 교통데이터를 이용했다.

먼저 API에 접근하기 위해 인증키를 발급 받는다.

실시간 영업소간 통행시간 페이지
이후 실시간 영업소간 통행시간 페이지 에 접속해 아래의 예제 실행하기를 클릭.

실시간 영업소간 통행시간 팝업
원하는 Request Parameter를 입력하고(필자는 key(여기서 키는 방금 발급받은 인증키), type, iStartUnitCode, iEndUnitCode만 작성) URL보기를 하면 URL이 출력되고 , 아래의 예제 실행하기를 통해 직접 볼 수도 있다.

이제, 캐글에 다음과 같이 입력해준다.

1
2
3
4
5
6
7
8
import requests
key = "발급받은 인증키"
type = "json"
url = "출력된 URL"
responses = requests.get(url)
print(responses)
json = responses.json()
json

을 입력해주면
팝업에서 보았던 예제를 직접 볼 수 있다.

필요한 정보가 있는 “realUnitTrtmVO” 항목을 가져오기 위해 다음 코드 입력

1
cars = json["realUnitTrtmVO"]

이것을 반복문을 통해 리스트, 딕셔너리 형태로 만들어준다.

1
2
3
4
5
6
7
8
9
10
data = []
for car in cars:
dic_df = {}
dic_df["date"] = car["stdDate"]
dic_df["time"] = car["stdTime"]
dic_df["destination"] = car["endUnitNm"]

data.append(dic_df)

data

아래는 아웃풋

1
2
3
4
5
6
7
8
9
10
[{'date': '20220103', 'destination': '수원신갈', 'time': '05:30'},
{'date': '20220103', 'destination': '수원신갈', 'time': '05:35'},
{'date': '20220103', 'destination': '수원신갈', 'time': '05:40'},
{'date': '20220103', 'destination': '수원신갈', 'time': '05:45'},
{'date': '20220103', 'destination': '수원신갈', 'time': '05:50'},
{'date': '20220103', 'destination': '수원신갈', 'time': '05:55'},
{'date': '20220103', 'destination': '수원신갈', 'time': '06 '},
{'date': '20220103', 'destination': '수원신갈', 'time': '06:00'},
{'date': '20220103', 'destination': '수원신갈', 'time': '06:05'},
{'date': '20220103', 'destination': '수원신갈', 'time': '06:10'}]

이렇게 딕셔너리로 구성된 리스트가 생성되었다.
이것을 Pandas Dataframe으로 변환후 엑셀시트로 출력하려면 다음과 같이 하면 된다.

1
2
3
import pandas as pd
df = pd.DataFrame(data) # 판다스 데이터프레임으로 변환
df.to_csv("temp.csv",index=False,encoding="euc-kr")

이렇게하면 설정된 곳으로 캐글에서 데이터프레임이 다운로드된다.

콜백(Callback)함수의 사용법

Plotly 를 사용하여 대시보드를 만드는 동안에 직면했던 여러 문제들중 해결에 꽤 오랜시간이 걸린 문제가 있었다.
바로 콜백함수에 대한 부분인데 처음보게된 콜백함수가 데코레이터가 적용된 그런 함수였기 때문에 굉장히 헷갈렸다.

콜백함수


콜백함수란 다른함수의 인자로써 이용되는함수, 어떤 이벤트에 의해 호출되어지는 함수를 말한다.
함수가 다른함수의 인자로 사용될 수 있다니, 잘 이해가 되지 않을 수 있다.

내가 접했던 콜백함수를 가져와 보면 이렇다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@app.callback(
Output('id_fig_age', 'Figure'),
Input('country-filter', 'value'))
def age_chart_func(value):
obj = px.bar(data,
x=data[data['Q3'] == value]['Q1'][1:].value_counts().sort_index().index,
y=data[data['Q3'] == value]['Q1'][1:].value_counts().sort_index().values,
)
obj.update_traces(hovertemplate='%{x}: %{y:.0f}',
marker_color='#E08E79',
marker_line_width=0,)
obj.update_layout(paper_bgcolor=colors['content-background'],
font_color=colors['text'],
plot_bgcolor=colors['plot_background'],
autosize=True)
obj.update_xaxes(title_text='Age Distribution')
obj.update_yaxes(title_text='Counts')
return obj

전체코드의 일부분이지만 함수를 설명하는데에는 문제가 없다.

먼저 가장 위에 있는 @app.callback가 무슨뜻인지 이해하지 못한다면 데코레이터 에 대해 간략히 보고 오면 좋다.
그리고 Output과 Input은 dash.dependencies 라이브러리에서 import 한 것인데, 기능을 살펴보기위해 코드대로 해석하자면

Input의 괄호안의 첫번째 인자(country-filter)와 ID가 같은 항목을 찾아 두번째 인자(country-filter 의 파라미터 value)를 아래에 있는 함수의 인자로 넣어주며, 인자를 통해 함수를 실행 후 나온 리턴을,
Output의 괄호안의 첫번째 인자(id_fig_age)와 ID가 같은 항목의 두번째 인자(Figure)로 입력되는 것이다.

위 코드에서 복잡해 보일 수 있는 부분인 px.bar ~ obj.update_yaxes 까지는 그냥 그래프를 그려주는 함수라고 생각하면된다.

이때 이 함수를 모두 실행하고 리턴하는 값인 obj 가 반환되어 Output인 ‘id_fig_age’의 ‘Figure’속성으로 입력되고 ‘id_fig_age’는 함수에서 작성된 그래프를 ‘Figure’로 갖게되어 화면에 표현해준다.

파이썬 데코레이터 (Python Decorator)

데코레이터란?


파이썬으로된 소스코드들을 보면, 가끔 다음과 같은 구문을 볼 수 있다.

1
2
3
@decorator
def func()
print("How to use Python")

본적은 있는것 같으나 어디에 어떻게 사용되는지 처음보는사람은 모를 수 있다.
데코레이터는 함수를 수정하지 않은 상태에서 추가기능을 구현할 때 사용한다.
일단 다음의 예시를 보자

1
2
3
4
5
6
7
8
def func1():
print("func1")

def func2():
print("func2")

func1()
func2()

위 두개의 함수에 각각 시작부분과 끝부분을 표기하고싶다면 아래와 같이 함수 시작, 끝부분에 print를 따로 넣어주어야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
def func1():
print("func1 start")
print("func1")
print("func1 end")

def func2():
print("func2 start")
print("func2")
print("func2 end")

func1()
func2()

함수가 한개, 두개라면 부담이 되지않겠지만 만약 10개, 100개, 1000개의 함수가 있고 그것을 수정해야한다면 여간 귀찮은 일이 아닐것이다.

이런 경우에 데코레이터를 사용하면 편리하다.
바로 다음 예시를 보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def dec(func):
def wrapper(func):
print(func.__name__, "start")
func()
print(func.__name__, "end")
return wrapper

def func1():
print("func1")

def func2():
print("func2")

dec_func1 = dec(func1)
dec_func1()
dec_func2 = dec(func2)
dec_func2()

'''
또는
dec(func1)()
dec(func2)()
'''
1
2
3
4
5
6
7
<Output>
func1 start
func1
func1 end
func2 start
func2
func2 end

위처럼 입력하게 될 경우 먼저 만들어졌던 dec 함수에 의해 func1, func2의 함수 출력부분에 시작과 끝을 나타내는 print가 같이 출력되게 할 수 있다.

위 코드에서 start 와 end 앞에 있는 func1,func2의 경우에는 함수의 이름이 출력되는것이고, 그 사이에 있는 func1,func2은 함수의 print 열이 출력된 것이다.

@가 있는 데코레이터 사용하기


그런데 처음에 예시로 보았던 @로 시작하는 데코레이터는 어디에도 보이지 않는다.
@를 사용하는 데코레이터는 어떻게 만드는 것일까?

@를 사용하는 데코레이터는 다음과 같이 작성한다.

1
2
3
@dec
def func1():
print("func1")

간결하게 적어서 이해가 어려울 수 있으니 이전 챕터의 가장 뒷부분 코드를 가져와 수정해보면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def dec(func):
def wrapper():
print(func.__name__, "start")
func()
print(func.__name__, "end")
return wrapper

@dec
def func1():
print("func1")

@dec
def func2():
print("func2")

func1()
func2()

결과는 같지만 무엇보다 출력부분이 매우 간결해졌다.

만약 한개의 함수에 데코레이터 여러개를 사용해야한다면 다음과 같이 할 수 있다.

1
2
3
4
5
@dec1
@dec2
@dec3
def func1():
print("func1")

코드가 위와 같을 때 여러개의 데코레이터가 지정되며 이때 데코레이터가 실행되는 순서는 위에서 아래 순으로 실행된다.

마지막으로 데코레이터를 그림으로 표현하면 다음과 같다.

데코레이터의 실행 과정

Reference

https://bluese05.tistory.com/30

파이썬(Python) with 구문

with 구문이 무엇인가?


보통 프로그램은 파일에 접근해서 파일 내용등을 읽고 쓰고 수정하는등의 일을 수행한 뒤 다시 그 파일을 마운트 해제 하는 패턴을 따른다.
예시로 사용자가 워드파일 문서 작업을 하고 있을 때 그 파일을 열고있는 동안 파일관리자가 그 문서의 이름을 바꾼다던지 파일의 경로를 변경한다던지 같은 파일에 접근을 필요로하는 행동을 타 프로그램에서 할 수 없게 된다.

결론만 말하자면 파일에 접근했으면(열었으면) 해제하는(닫아주는) 일을 빼먹지 않고 해주어야 한다는 것이다.
보통 close() 같은 메소드를 사용하여 파일을 닫아주지만 이는 문제점이 있다.
파일 처리를 수행하는 도중에 오류가 발생하게되면 아래에있는 close() 문을 실행할 수 없고 파일을 닫을수 없게된다.

with 문은 그 구문을 실행했을 때 오류가 발생하던 하지않던 마지막에 close 를 해주도록 하는 것이다.

with문 사용 예시


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 일반적인 코드
file = open('textfile.txt', 'r')
contents = file.read()
file.close()

# try finally를 사용한 코드
try:
file = open('textfile.txt', 'r')
contents = file.read()
finally:
file.close()

# with 구문을 사용한 코드
with open('textfile.txt', 'r') as file:
contents = file.read()

위의 세가지 코드는 모두 같은 내용이지만 첫번째 코드를 실행할때 contents = file.read() 행에서 에러가 난다면 file.close()를 실행하지 못해 파일을 닫을 수 없다.
그러나 아래의 두가지 코드는 에러가 발생해도 코드를 닫을 수 있을 뿐더러 with문은 더욱 간결하여 보기 편하다.



여러개의 파일 관리하기


두 개 이상의 파일을 동시에 사용할 때 with as 문을 사용하는 방법이다.
두개의 with as 문을 겹쳐도 되고, 하나의 with문에 두 개 이상의 파일을 열어도 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
with open('textfile_a.txt', 'r') as a:
with open('textfile_b.txt', 'w') as b:
a_file = a
b_file = b.write('hello wolrd')

with open('textfile_a.txt', 'r') as a, open('textfile_b.txt', 'w') as b:
a_file = a
b_file = b.write('hello world')

# 파이썬 3.10.0 b1 버전부터는 아래처럼도 가능하다
with (
open('textfile_a','w') as a,
open('textfile_b','w') as b,
open('textfile_c','w') as c
):
a.write('apple')
b.write('banana')
c.write('count')

class로 context manager 구현하기


1
2
3
4
5
6
7
class File(object):
def __init__(self, file_name, method):
self.file_obj = open(file_name, method)
def __enter__(self):
return self.file_obj
def __exit__(self, type, value, trace_back):
self.file_obj.close()

위와 같이 정의를 하고 아래처럼 실행해 보면

1
2
with File('demo.txt', 'wb') as opened_file:
opened_file.write('Hola!')
  1. with 문은 File class의 __exit__메소드를 저장
  2. File class의 __enter__메소드를 호출
  3. __enter__메소드는 파일을 열고 파일을 반환
  4. 열려진 파일은 변수명 opened_file에 저장
  5. .write()을 통해 내용 작성
  6. with문 이기 때문에 __exit__문을 호출
  7. __exit__문을 통해 파일 닫음

위와같은 실행순서로 context manager를 구현 할 수 있다.

References.

https://tempdev.tistory.com/22
https://ddanggle.gitbooks.io/interpy-kr/content/ch24-context-manager.html

파이썬(Python) 사용자 지정 함수

사용자 지정 함수란?


파이썬에서(다른프로그래밍 언어, 스크립트 언어에서도) 함수란, 소프르웨어에서 특정 동작을 수행하는 일정 코드부분을 의미한다.

하나의 큰 프로그램을 여러부분으로 나누어주기 때문에 같은 함수를 여러 상황에서 여러차례 호출할 수 있고, 일부분을 수정하기 쉽다는 장점을 지닌다.

파이썬에서는 미리 정의 되어있는 built in 함수(내장함수)가 있고. 또, 사용자가 필요에 의해 정의를 한 사용자 지정 함수가 존재한다.

파이썬에서의 함수 모형


파이썬 함수의 기본 모형

1
2
3
4
def 함수명() :
실행문
실행문
...

이와 같은 구조인데 함수를 정의하는 def뒤에 함수명이 오고 소괄호()를 붙인 다음 콜론:을 붙여주고, 다음줄에 원하는 실행문을 들여쓰기하여 사용하면 된다.

1
2
def func() :
print('python function')

위는 기본 모형을 응용하여 함수를 정의한 것이다. 이는 입력값도, 반환값도 없는 함수이며 값이 있는 함수에 대해서는 후술하겠다.

그러나 위 코드는 함수를 정의한 것이지 사용을 한 것이 아니다. 그렇기 때문에 함수를 사용하기 위해서는 함수의 사용법을 알아야 한다.

1
2
3
4
5
def func() :
print('python function')

#함수 호출
func()
Output
1
python function

func()함수는 입력값이 없기때문에 호출시에 입력값을 넣어주지 않고 괄호만 입력해 준다.



입력값만 있는 함수


1
2
3
4
5
6
def func2(a) :
print('입력한 문자는 ' + a + ' 입니다.')

func2("비행기")
func2("자동차")
func2("파이썬")
Output
1
2
3
입력한 문자는 비행기 입니다.
입력한 문자는 자동차 입니다.
입력한 문자는 파이썬 입니다.

func2()함수의 입력값이 a 에 입력되어 출력 된 것을 볼 수 있다.



리턴값만 있는 함수


1
2
3
4
def func3() :
return "12345"

print(func3())
Output
1
12345

func3()의 값이 리턴되어 print()를 통해 출력된 것을 알 수 있다.



입력,리턴값이 모두 있는 함수


1
2
3
4
def func4(a, b) :
return a + b

print(func4(10,20))
Output
1
30

a,b의 입력값을 더하는 함수에 10,20의 값을 주었더니 예상대로 30이 출력 되었다.



기본 인자 값


입력이 있는 함수를 여러 곳에 사용할 때 반복되는 값에 대해서는 기본적인 값을 지정할 수 있다.
기본값은 입력 = 값의 형태로 작성된다.

1
2
3
4
5
def func_b(a,b,c=5) :
return a*b+c

print(func_b(2,3,10))
print(func_b(2,3))
Output
1
2
16
11

출력에서처럼 기본값이 주어진 c 인자에 별다른 값을 넣지 않으면 기본값 5로 계산되어 10이들어간 결과보다 5가 낮아지게 된다.

이렇게 기본 인자를 줄 때는 주의 할 점이 한 가지 있는데 바로 인자의 순서에 맞게 넣어주어야 한다는 것과, 기본값과 입력값이 없으면 에러가 난다는 것이다.
다음 예시를 보자.

1
2
3
4
def func_b2(a,b=5,c) :
return a*b+c

print(func_b2(2,3))

위와 같이 값을 주게 된다면 어떨까?
b에 기본값이 있으니 a와 c에 각각 2와 3이 입력된다고 생각한 사람도 있을 것이다.
그러나 이 생각은 적어도 사용자 지정 함수에서는 옳지 않다.

이 코드가 불가능한 데에는 두 가지 이유가 있다.

첫 번째로는 a에는 2가 들어가는 것이 맞겠지만, b에 기본값이 있더라도 두 번째 입력값 자리에 3을 넣게 되는 순간 그 숫자는 b에 입력되기 때문에 결국엔 기본값이 없는 c는 어떠한 값도 입력받지 못하게 되기 때문이고,

두 번째 이유로는 c의 인자에 기본값이 없음에도 앞에 있는 b의 인자에 기본값이 있으므로 아예 성립할 수 없는 코드이다.
그러므로 기본값을 부여받은 인자는 항상 뒤에 배치해야 한다.



키워드 인자


키워드 인자는 함수를 정의할때 인자에 키워드를 부여하고 함수를 호출할 때 키워드=값의 형태로 넣어줄 수 있는 인자이다.
그냥 인자에 값을 넣어주는것과 뭐가 다르냐?라는 의문이 들 수도 있다.
다음 예시를 보자.

1
2
3
4
def score(kim=100, lee=100, park=100, choi=100) :
print('score = kim :', kim, 'lee :',lee, 'park :',park, 'choi :',choi)

score(park= 50)
Output
1
score = kim : 100 lee : 100 park : 50 choi : 100

이렇게 중간의 인자만 키워드=값의 형태로 입력해 값을 변경해 줄 수 있다.
예제처럼 여러 기본값이 있고 그중 몇 가지의 기본값만 바꿔 주어야 할 때 용이하게 쓸 수 있다.

Arbitrary Argument Lists (임의 인자 리스트)


Arbitrary Argument Lists는, 여러인자를 함수에 잔달하는 방법들중 하나이다.

함수내부에서 이 인자들은 튜플로 감싸져있으며 이는*argsarguments 생성자를 사용하여 정의 된다.

1
2
3
4
5
6
7
8
9
10
def avg_score(*numbers) :
s = 0
count = 0
for i in numbers:
s += i
count += 1
return s / count

print('국어와 수학점수의 평균은{}점 입니다'.format(avg_score(95, 87)))
print('입력된 숫자들의 평균은{} 입니다.'.format(avg_score(42,63,45,32,48)))
Output
1
2
국어와 수학점수의 평균은91.0점 입니다
입력된 숫자들의 평균은46.0 입니다.

위 코드에서는 *args*numbers로 대체했다.
이처럼 함수를 호출 할 때에 숫자를 몇가지를 넣어도 사용이 가능하다.



Lambda 함수


우리가 앞에서 배웠던 대로 사용자 지정 함수를 정의하고 사용하여 평균을 구하라고 한다면 아마 다음과 같을것이다.

1
2
3
4
5
def avg(x,y):
return(x + y) / 2
print(avg(5,13))

>> 9.0

그러나 파이썬은 Lambda함수를 통해서 이 코드를 더욱 짧게 줄일수 있다.

1
2
3
print((lambda x,y: (x + y)/2)(5,13))

>> 9.0

그러나 배우는 입장인 내 눈으로 단점을 찾아보자면 함수인데 정의를 하는 부분이 따로 없다 보니, 출력할 일이 여러 번 생긴다면 번거로워 질 것 같다.
그러니 앞으로 호출 횟수에 따라 적다면 람다 함수를, 많다면 기본적인 사용자 지정 함수를 사용하는 방식이 좋을 듯하다.



References

파이썬(Python) 기본 문법 - 1

이 포스트는 필자의 정확한 파이썬 문법을 익히고 필요할때 찾아보기 위해 서술한 것이다.

Hello World


어떤 프로그래밍언어든 배우기 시작하면 출력하고 보는 Hello world, 파이썬에서는 다음과 같이 출력한다.

1
print("Hello, world!")

Output:

Hello, world!

당연하게도 Hello, world 이외의 다른 문장이 들어가면 그대로 출력되며
print() 에서 괄호 내부에 출력을 해주고싶은 변수나 문장을 입력하면 된다, 문장의 경우는 따옴표로 묶어줘야 출력이 된다.

주석처리


접기 / 펼치기

프로그래밍 언어마다 주석처리를 해주는 방법이 다르다, 파이썬의 경우에는 다음과 같이 주석처리한다.

1
2
3
4
5
6
7
# 한줄을 주석처리하는 방법입니다.
"""
여러줄을
한번에 주석처리하는
방법입니다.
"""
print("Hello, world!")

Output:

Hello, world!

위처럼 작성하고 실행시키면 나머지 줄은 모두 주석처리되고 가장 아랫줄인 Hello, world만 출력이 되는걸 볼 수 있다.

변수의 종류


접기 / 펼치기

변수(Variable)는 (문자나 숫자 같은) 값을 담는 컨테이너로 값을 유지할 필요가 있을 때 사용한다. 여기에 담겨진 값은 다른 값으로 바꿀 수 있다. 변수는 마치 (사람이 쓰는 언어인) 자연어에서 대명사와 비슷한 역할을 한다.

출처 : 생활코딩 - 변수

다른 프로그래밍언어와 같이 파이썬 역시 다양한 변수의 종류(타입)가 있는데 이번 단락에서는 그것에 대해 알아보겠다.

int타입 (정수형)

1
2
num_int = 1
print(type(num_int))

변수에 값을 정수로 주고 그 변수의 타입을 알아본 예제, 출력을 하게되면 <class 'int'>가 줄력된다.

float타입 (실수형)

1
2
num_float = 0.2
print(type(num_float))

변수에 값을 실수로 주고 그 변수의 타입을 출력한 예제, 출력을 하게되면 <class 'float'>가 출력된다.

bool타입 (논리형)

1
2
bool_true = True
print(type(bool_true))

변수에 값을 논리타입(True or False)으로 주고 그 변수의 타입을 출력한 예제, 출력하면 <class 'bool>이 출력된다.

None타입

1
2
none_x = None
print(type(none_x))

Null을 나타내는 자료형이다, None라는 한가지 값만 가질 수 있다. (왜 필요한지는 아직 모르겠다)

사칙연산


접기 / 펼치기

파이썬에서의 사칙연산은 일반적인 사칙연산과 같다.
그리고 나눈후 정수의값만 구하는 //, 나머지를 구하는 %, 거듭제곱을 뜻하는 ** 등의 연산자가 있다.

1
2
3
4
5
6
7
8
9
a = 3
b = 2
print('a + b = ', a+b)
print('a - b = ', a-b)
print('a * b = ', a*b)
print('a / b = ', a/b)
print('a // b = ', a//b)
print('a % b = ', a%b)
print('a ** b = ', a**b)

Output:

a + b =  5
a - b =  1
a * b =  6
a / b =  1.5
a // b =  1
a % b =  1
a ** b =  9

위처럼 각각 계산이 된걸 알 수 있다.

정리하면 아래와 같다

연산자 내용
+ 두 변수의 합을 계산
- 두 변수의 차를 계산
* 두 변수의 곱을 계산
/ 두 변수로 나눈 결과를 float 형으로 반환
// 두 변수로 나눈 결과에서 정수 부분만 취함
% 두 변수로 나눈 결과에서 나머지 값만 가져옴
** i**j일 경우, i의 j만큼 제곱하여 계산 (예: 2 ** 4 = 24 = 16)

논리형 연산자


접기 / 펼치기

논리형 연산자에는 andor이 있다.
and연산자는 두 조건이 모두 참일때 True가 되며 or의 경우 두 조건중 하나라도 참일때 True가 된다.

and연산자

1
2
3
4
print(True and True)
print(True and False)
print(False and True)
print(False and False)

Output:

True
False
False
False

위 결과처럼 두 조건 모두 참일때만 True를 반환한다.
표로 나타내면 다음과 같다.

변수1 변수2 AND 연산결과
True True True
True False False
False True False
False False False

or 연산자

1
2
3
4
print(True or True)
print(True or False)
print(False or True)
print(False or False)

Output:

True
True
True
False

위 결과처럼 두 조건 중 하나만 참이라도 True를 반환한다.
표로 나타내면 다음과 같다.

변수1 변수2 AND 연산결과
True True True
True False True
False True True
False False False

비교 연산자


접기 / 펼치기

비교 연산자에는 >,<,>=,<=이 있다.
일단, 예제를 보자.

1
2
3
4
print(4 > 3)
print(4 < 3)
print(4 >= 3)
print(4 <= 3)

Output:

True
False
True
False

예제처럼 결과는 논리타입으로 출력된다.

문자열 연산


접기 / 펼치기

정수나 실수 논리타입뿐만 아니라 문자열도 연산이 가능하다.
다만 문자열을 뒤에 덧붙이는+연산자, 문자열을 횟수만큼 반복해주는*연산자만 사용이 가능하다.

1
2
3
str1 = "Python "
str2 = "Editor "
print('str1 + str2 = ', str1 + str2)

Output:

Python Editor

+연산자의 경우 위처럼 문자열 두 개가 나란히 이어붙혀져 출력이 되며,

1
2
greet = str1 + str2
print('greet * 3 = ', greet * 3)

Output:

Python Editor Python Editor Python Editor 

*연산자의 경우 변수에 담긴 문자열이 정해준 횟수만큼 반복되어 나열된다.

문자열 인덱싱


접기 / 펼치기

문자열이 있는경우 숫자을 통해 문자열에서 특정 문자만을 출력할 수 있는데 이를 Indexing 이라고 한다.
Hello world이라는 문자열이 있다고 하자 그럼 문자열의 각 인덱스는 다음과 같다.

문자열 H e l l o w o r l d
인덱스 0 1 2 3 4 5 6 7 8 9 10

이처럼 각 글자마다 인덱스가 배정되며 공백에도 인덱스가 배정된다.
인덱스를 사용하면 다음과 같은 것도 가능하다.

1
2
3
4
text_ex = "Hello world"
print(text_ex[2])
print(text_ex[6:10])
print(text_ex[2:11:2])

Output:

l
worl
lowrd

위 예제는 문자열을 담은 변수에 인덱싱을 한 것이다
첫번째 줄은 인덱스’2’의 문자를 가져오는 것인데 인덱스는 0부터 시작하므로 (2번째가아닌)3번째인’l’을 출력한것이다.
두번째 줄은 인덱스’6’부터 ‘9’까지(두번째인덱스-1)의 숫자를 가져오는 것이므로 ‘worl’이 출력되었다.
세번째 줄은 인덱스’2’부터 ‘10’까지를 가져오되, 한칸씩 건너뛰고(세번째 숫자가 3이므로) 가져오는것이다.

리스트(list)


접기 / 펼치기

리스트는 여러개의 문자열, 변수, 숫자 등을 담을수 있는 자료구조이다.
리스트의 장점은 다음과 같다.

  • 인덱스 번호로 빠른 접근이 가능하다.
  • 데이터의 위치에 대해 직접적인 접근(Access)가 가능하다.
    1
    fruit = [['apple', 'banana', 'cherry'], 123]
    위가 리스트의 형태이다.
    리스트의 값은 기본적으로 인덱스가 배정된다 이때는
    1
    print(fruit[0])
    Output: [‘apple’, ‘banana’, ‘cherry’]
    위와 같은 형태로 나타낼 수 있으며 해당 인덱스의 요소가 리스트라면 리스트 전체를 출력한다.

만약 위처럼 리스트가 중첩된 형태라면

1
print(fruit[0][1])

Output:

banana

위처럼 출력이 가능하며 이때 리스트의 요소중 해당 인덱스의 요소가 출력된다.
물론 이 때도 출력된 문자열에서 다음과 같이 문자열의 요소를 출력하는것도 가능하다.

1
print(fruit[0][1][3])

Output:

a

위와같이 결과가 출력된다.

리스트값 수정, 추가, 삭제하기


접기 / 펼치기

리스트가 여러 요소들의 집합이다보니 리스트의 값에 변동이 필요할 때가 있다.
리스트는 값의 수정, 추가, 삭제가 가능하므로 기능과 문법에 대해 알아둘 필요가 있다.

리스트 값 수정하기

1
2
3
a = [0,1,2]
a[1] = "b"
print(a)

Output:

[0, 'b', 2]

별다른 문법없이 리스트의 인덱스에 값을 넣어주니 수정이 되는것을 알 수 있다.

리스트 값 추가하기

  • append

    1
    2
    3
    4
    5
    6
    7
    a = [100, 200, 300]
    a.append(400)
    print(a)

    b = [500,600]
    a.append(b)
    print(a)

    Output:

    [100, 200, 300, 400]
    [100, 200, 300, 400, [500, 600]]
    리스트명.append(값)을 통해서 리스트에 값을 추가할 수 있으며 한개의 값만 추가할 수 있다.
    리스트의 경우엔 한가지 값이며 추가할 경우 중첩된 리스트의 형태로 추가가 된다.

  • extend

    extendappend와 거의 같지만 다른점이 하나 있습니다.
    append는 인자(리스트, 튜플 등)를 주어도 인자 그대로를 리스트에 추가하지만,
    extend는 인자를 줄 경우 인자의 값 하나하나를 리스트에 추가한다.

    1
    2
    3
    4
    a = [2, 9, 3]
    b = [1, 2, 3]
    a.extend(b)
    print(a)

    Output:

    [2, 9, 3, 1, 2, 3]
    결과와 같이 append와 비교했을때 extend된 인자의 값 하나하나가 추가된걸 볼 수 있다.

  • insert

    insert는 입력해준 위치의 인덱스에 값을 추가해준다.

    1
    2
    3
    4
    a = [1,2,3]
    print(a)
    a.insert(1,'abc')
    print(a)

    Output:

    [1,2,3]
    [1,’abc’,2,3]

리스트 값 삭제하기

  • remove

    1
    2
    3
    4
    5
    6
    7
    a =[1,2,1,2]
    #리스트의 첫번째 1이 삭제
    a.remove(1)
    print(a)
    #리스트의 두번째 였던 1이 삭제
    a.remove(3)
    print(a)

    Output:

    [2, 1, 2]
    [2, 2]
    리스트명.remove()는 괄호내의 값을 삭제한다.
    만약 값이 리스트내에서 중복될경우 가장 앞에 있는 값을 삭제한다.

  • del

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    a = [0,1,2,3,4,5,6,7,8,9]

    # 1 삭제
    del a[1]
    print(a)

    b = [0,1,2,3,4,5,6,7,8,9]
    # 범위로 삭제
    del b[1:3] #list는 항상 시작하는 index부터, 종료하는 n의 n-1까지의 범위를 잡아준다.
    print(b)

    Output:

    [0, 2, 3, 4, 5, 6, 7, 8, 9]
    [0, 3, 4, 5, 6, 7, 8, 9]
    del 리스트명[인덱스]는 리스트의 인덱스에 위치한 값을 삭제해준다.
    인덱스값에 범위를 주고싶다면 0:4 처럼 넣을수 있으며 이때는 0에서 3번째 값까지 삭제가 된다.

  • pop

    1
    2
    3
    4
    5
    a = [0,1,2,3,4]
    r = a.pop(1)

    print(a)
    print(r)

    Output:

    [0, 2, 3, 4]
    1
    리스트명.pop()은 괄호내의 값을 해당 리스트에서 끄집어낸다.

튜플(tuple)


접기 / 펼치기

튜플은 리스트와 비슷하게 여러개의 문자열, 변수, 숫자 등을 담을수 있는 자료구조이다.
튜플과 리스트의 가장 차이점으로는 튜플은 값에대한 수정이 불가하다는 점이다.
그렇다면 튜플은 무슨 장점이 있느냐 라고 반문할 수 있는데 리스트와 비교한 튜플의 장점은 다음과 같다.

  • 메모리 사용량이 적다.
  • 생성 시간이 빠르다.
  • 인덱스를 사용하여 튜플의 데이터에 접근하는 시간이 비교적 짧다.

튜플의 문법, 기본형태는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
tuple1 = (0) # 끝에 콤마(,)를 붙이지 않았을 때
tuple2 = (0,) # 끝에 콤마(,)를 붙여줬을 때
tuple3 = 0,1,2

print(tuple1)
print(tuple2)
print(tuple3)

print(type(tuple1)) # 콤마(,)를 붙여주지 않으면 튜플이 아닙니다.
print(type(tuple2)) # 콤마(,)를 붙여주어야 튜플 자료형 입니다.
print(type(tuple3)) # 여러개의 값 일경우 괄호를 없애주어도 튜플 자료형 입니다.

Output:

0
(0,)
(0, 1, 2)
<class 'int'>
<class 'tuple'>
<class 'tuple'>

튜플을 생성할때 튜플이 되기위해서는 콤마(,)가 필수적이다.
콤마를 작성하지 않으면 타입을 출력했을때 튜플이 아닌 입력한 변수형태로 출력이 된다.

튜플역시 리스트와 같이 인덱싱및 슬라이싱이 가능하다.

튜플의 연산

튜플도 연산이 가능한데, 더하거나 곱하는 +, * 연산자만 사용이 가능하다.

1
2
3
4
t1 = (0,1,2,3,4)
t2 = ('a','b','c')
t3 = t1+t2
print(t3)

Output:

(0, 1, 2, 3, 4, 'a', 'b', 'c')

딕셔너리


접기 / 펼치기

딕셔너리는 키와 그에따른 값으로 구성되어있는 파이썬의 자료구조이다.

1
2
3
4
5
dic = {'teacher':'alice', 'class': 5, 'studentid': '15', 'list':[1,2,3]}

print(dic['teacher'])
print(dic['class'])
print(dic['list'])

Output:

alice
5
[1, 2, 3]

를 출력하면 그와 대응하는 이 출력되는 자료구조이며 자료에 순서가 없는논시퀀스 자료형이다.

1
2
3
a = {'name': 'bob', 'job': 'farmer', 'age': 35}
a.keys()
a.values()

Output:

dict_keys(['name', 'job', 'age'])
dict_values(['bob', 'farmer', 35])

이렇게 키만 출력할수도, 값만 출력할수도 있다.

집합 연산자


접기 / 펼치기

파이썬에도 집합연산이 있고, 자료구조들의 합,교,차집합에 대한 연산을 할수 있다.
기호는 |,&,-이며, 각각의 예시는 다음과 같다.

1
2
3
4
5
a = {1,2,3,4}
b = {3,4,5,6}
print(a|b)
print(a&b)
print(a-b)

Output:

{1, 2, 3, 4, 5, 6}
{3, 4}
{1, 2}

if 조건문


접기 / 펼치기

조건문이란 작성자가 명시한 조건식의 결과인 boolean값이 참인지 거짓인지에 따라 달라지는 계산이나 상황을 수행하는 문장이다.

1
2
3
4
5
6
7
8
9
10
a = -5

if a>5:
print('a는 5이상입니다')

elif a > 0:
print("a는 0초과, 5이하입니다")

else:
print("a는 음수입니다")

Output:

a는 음수입니다.

조건식에는 기본적으로 조건식이 들어가지만 TrueFalse등의 직접적인 bool형 변수가 삽입될수도 있으며, and,or 등과 결합하여 여러가지의 조건식을 사용할수도 있다.

반복문 (for,while)


접기 / 펼치기

같은동작을 여러번 반복해야 할 때 같은코드를 여러번 적어넣는건 비효율적이다.
그럴때 반복문을 사용하면 훨씬 적은양의 코드로도 같은효과를 낼 수 있다.

  • for문

  • for문의 기본 구조
    1
    2
    3
    for 변수 in 리스트(또는 튜플, 문자열) :
    수행할 문장1
    수행할 문장2
    리스트나 튜플, 문자열의 첫 번째 요소부터 마지막 요소까지 차례로 변수에 대입되어 “수행할 문장1”, “수행할 문장2” 등이 수행된다.
    1
    2
    3
    a = ['1','2','3']
    for i in a :
    print(i)
    Output: 1
    2
    3

리스트 a의 첫번째 값인 1이 i에 대입되고 print(i)가 출력된다.
다음엔 두번째 값인 2가 대입되고 출력된다.
이것을 마지막 값까지 반복한다.

  • while문

  • while문의 기본 구조
    1
    2
    3
    4
    5
    while <조건문>:
    <수행할 문장1>
    <수행할 문장2>
    <수행할 문장3>
    ...
    while문은 for보다는 간단하다. while, 조건문, 실행문 이 세개면 완성되기 때문이다.
    이러한 특성때문에 while문은 조건문을 거짓으로 만들어주는 문장이 없다면 무한실행된다. 프로그램 뻗는다
    간단한 예제를 보면 다음과 같다.
    1
    2
    3
    4
    i = 0
    while i <= 5 :
    print("{}번째 반복입니다.".format(i))
    i += 1
    Output: 0번째 반복입니다.
    1번째 반복입니다.
    2번째 반복입니다.
    3번째 반복입니다.
    4번째 반복입니다.
    5번째 반복입니다.
    변수 i로 인해 자동으로 조건식이 False가 되면서 while문이 종료되는 모습이다.
    이렇듯 while문은 조건문을 거짓으로 만들어주는 무엇인가가 없다면 종료되지않는다.