6주간의 혼공학습단 일정이 마무리되었다.
혼자 공부하는 데이터 분석도 같이 하려고 했는데 욕심이었던 것 같다😅
그래도 혼공파를 끝낸 것이 너무 뿌듯하다!
내가 시작해놓고 제대로 마무리하지 않은 경우가 많았기 때문에 이번에도 자신이 없었지만 마지막까지 올 수 있었다.
내가 공부한 부분을 봐주시는 분들이 있다고 생각하니 늦어도 제출해야 한다라는 의무감이 생겨서 혼자 할 때보다 더 집중하게 되고 책의 마지막 장을 넘길 수 있게 된 것 같다.
매번 댓글로 응원해주시고 동기 부여해주신 혼공족장님과 제 게시물을 읽어주시고 함께 혼공단에 참여한 모든 분께 감사드립니다!
정말 감사합니다. 모두 건강하세요!!🙇♀️
p.342 [직접 해보는 손코딩: BeautifulSoup 스크레이핑 실행하기]
예제 실행 후 결과 화면 캡처하기
혼공 용어 노트에 나만의 언어로 객체, 클래스, 인스턴스, 생성자, 메소드
정리하고 공유하기
📖 외부 모듈
파이썬이 기본적으로 제공해 주는 것이 아니라, 다른 사람들이 만들어 배포하는 모듈.
pip install 모듈 이름 # 명령 프롬프트 창에서 실행
conda install beautifulsoup4 # 가상환경에 설치
pip list
BeautifulSoup() # 사용 방법 → 단순한 함수 X, 클래스의 생성자 O
⌨️ BeautifulSoup 모듈 이용 : 날씨 가져오기
from urllib import request
from bs4 import BeautifulSoup
# urlopen() 함수로 기상청 전국 날씨 읽기
target = request.urlopen("http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=108")
# BeautifulSoup 사용해 웹 페이지 분석
soup = BeautifulSoup(target, "html.parser")
# location 태그 찾기
for location in soup.select("location"):
# 내부 city, wf, tmn, tmx 태그 찾아 출력
print("도시:", location.select_one("city").string)
print("날씨:", location.select_one("wf").string)
print("최저 기온:", location.select_one("tmn").string)
print("최고 기온:", location.select_one("tmx").string)
print()
🖥️ 결과
pip install flask
# 윈도우 사용자
set FLASK_APP=파일 이름.py
flask run
# 맥, 리눅스 사용자
export FLASK_APP=파일 이름.py
flask run
⌨️ Flask 모듈 사용
from flask import Flask
app = Flask(__name__)
@app.route("/") # @app.route() : 데코레이터
def hello():
return "<h1>Hello World!</h1>"
🖥️ 결과
📖 Flask 모듈 : @app.route(경로)
- '<경로>에 들어갈 때 실행할 함수' 지정하는 형태로 사용.
- 함수에서 리턴하는 문자열 기반 HTML 파일을 웹 브라우저에 제공.
⌨️ BeautifulSoup 스크레이핑 실행
# 모듈 읽어들임
from flask import Flask
from urllib import request
from bs4 import BeautifulSoup
# 웹 서버 생성
app = Flask(__name__)
@app.route("/")
def hello():
# urlopen() 함수로 기상청 전국 날씨 읽음
target = request.urlopen("http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=108")
# BeautifulSoup 사용해 웹 페이지 분석
soup = BeautifulSoup(target, "html.parser")
# location 태그 찾기
output =""
for location in soup.select("location"):
# 내부 city, wf, tmn, tmx 태그 찾아 출력
output += "<h3>{}</h3>".format(location.select_one("city").string)
output += "날씨: {}<br/>".format(location.select_one("wf").string)
output += "최저/최고 기온: {}/{}"\
.format(\
location.select_one("tmn").string,\
location.select_one("tmx").string)
output += "<hr/>"
return output
🖥️ 결과
구분 | 설명 |
---|---|
라이브러리(library) | 정상적인 제어를 하는 모듈 |
프레임워크(framework) | 제어 역전 발생하는 모듈 |
📖 라이브러리 (library)
- 역전되지 정상적인 제어.
- 개발자가 모듈 기능 호출하는 형태의 모듈.
- 개발자가 모듈의 함수 호출 = 일반적 제어 흐름- math 모듈
# 모듈 읽어들임 from math import sin, cos, tan, floor, ceil # sin 구함 print("sin(1):", sin(1))
📖 프레임워크 (framework)
- 제어 역전(IoC, Inverse of Control) : 제어가 역전되어 있음.
- 모듈이 개발자의 코드를 실행하는 형태의 모듈.
- 모듈이 개발자의 함수 호출 = 제어 역전됨- Flask 모듈
from flask import Flask app = Flask(__name__) # 웹 서버 생성 @app.route("/") def hello(): return "<h1>Hello World!</h1>"
📖 함수 데코레이터
- 함수에 사용되는 데코레이터.
- 대상 함수의 앞뒤에 꾸밀 부가적 내용 또는 반복 내용을 데코레이터로 정의해 손쉽게 사용.
⌨️ 함수 데코레이터
# 함수 데코레이터 생성
def test(function):
def wrapper():
print("인사가 시작되었습니다.")
function()
print("인사가 종료되었습니다.")
return wrapper
# 데코레이터 붙여 함수 만듦
@test
def hello():
print("hello")
# 함수 호출
hello()
🖥️ 결과
❓ 왜 데코레이터 사용해서 복잡하게 작성할까?
- 데코레이터 사용 → functools라는 모듈 이용 가능
- 함수 데코레이터 사용 → 매개변수 등 전달 가능
➡️ 반복 구문 많을 때 소스 가독성 ⬆️ & 매우 유용 사용 가능.
# 함수로 데코레이터 생성
def test(function):
@wraps(function)
def wrapper(*arg, **kwargs):
print("인사가 시작되었습니다.")
function(*arg, **kwargs)
print("인사가 종료되었습니다.")
return wrapper
📖 functools
- 고차함수(high order functions) 위해 설계된 라이브러리.
- 호출 가능한 기존 객체, 함수 사용해 다른 함수 반환 & 활용 가능.
→ 기존 파이썬 함수 재사용해 원래 함수처럼 작동하는 새 부분 객체 반환
✅ 모듈 만드는 방법
- 파이썬 파일 만든다.
- 모듈 내부에 변수, 함수 등 넣어줌.- 외부에서 읽어 들인다.
__name__
- 변수
- 엔트리 포인트(entry point) / 메인(main) : 프로그램의 진입점
모듈의 __name__
- 엔트리 포인트 아니지만 엔트리 포인트 파일 내에서 import되어 모듈 내 코드 실행됨
- 모듈 내에서 __name__ 출력 → 모듈 이름 나타남.
__name__ 활용
- 엔트리 포인트 파일 내부 : __name__ = "__main__"
→ 현재 파일이 모듈로 실행되는지, 엔트리 포인트로 실행되는지 확인 가능
# 현재 파일이 모듈 실행 / 엔트리 포인트 실행 인지 확인해줌
if __name__ == "__main__":
print .. # 엔트리 포인트일 때만 실행
📖 패키지 (package)
- 모듈 모여서 구조 이룬 것.
- 모듈(module) : import로 가져오는 모든 것.
- pip(Python Package Index) : 패키지 관리 시스템(Package Management System)
from <패키지 이름> import* # 이 리스트에 지정된 모듈들 전부 읽어짐.
비교 | 텍스트 데이터 | 바이너리 데이터 |
---|---|---|
구분 방법 | 텍스트 에디터로 읽기 O | 텍스트 에디터로 읽기 X |
장점 | 사람이 쉽게 읽기 O, 텍스트 에디터로 쉽게 편집 O | 용량 작음 |
단점 | 용량 큼 | 사람이 쉽게 읽을 수 X, 텍스트 에디터 편집 X |
📖 객체(object)
- 여러 가지 속성 가질 수 있는 대상.
- 추상화(abstraction) : 프로그램에서 필요한 요소만으로 객체 표현하는 것.
⌨️ 딕셔너리로 객체 만들기
# 학생 리스트 선언
students = [
{"name": "윤인성", "korean": 87, "math": 98, "english": 88, "science": 95},
{"name": "연하진", "korean": 92, "math": 98, "english": 96, "science": 98},
{"name": "구지연", "korean": 76, "math": 96, "english": 94, "science": 90},
{"name": "나선주", "korean": 98, "math": 92, "english": 96, "science": 92},
{"name": "윤아린", "korean": 95, "math": 98, "english": 98, "science": 98},
{"name": "윤명원", "korean": 64, "math": 88, "english": 92, "science": 92},
]
# 학생 한 명씩 반복
print("이름", "총점", "평균", sep="\t")
for student in students:
# 점수의 총합, 평균 구함
score_sum = student["korean"] + student["math"] + student["english"] + student["science"]
score_average = score_sum / 4
# 출력
print(student["name"], score_sum, score_average, sep="\t")
🖥️ 결과
⌨️ 위의 코드를 객체 만드는 함수 이용해 만들기
# 딕셔너리 리턴하는 함수 선언
def create_student(name, korean, math, english, science):
return{
"name": name,
"korean": korean,
"math": math,
"english": english,
"science": science
}
# 학생 리스트 선언
students = [
create_student("윤인성", 87, 98, 88, 95),
create_student("연하진", 92, 98, 96, 98),
create_student("구지연", 76, 96, 94, 90),
create_student("나선주", 98, 92, 96, 92),
create_student("윤아린", 95, 98, 98, 98),
create_student("윤명원", 64, 88, 92, 92)
]
# 학생 한 명씩 반복
print("이름", "총점", "평균", sep="\t")
for student in students:
# 점수의 총합, 평균 구함
score_sum = student["korean"] + student["math"] + student["english"] + student["science"]
score_average = score_sum / 4
# 출력
print(student["name"], score_sum, score_average, sep="\t")
🖥️ 결과
⌨️ 위의 코드에서 학생을 매개변수로 받는 형태의 함수로 만들기
# 딕셔너리 리턴하는 함수 선언
def create_student(name, korean, math, english, science):
return{
"name": name,
"korean": korean,
"math": math,
"english": english,
"science": science
}
# 힉셍 처리하는 함수 선언
def student_get_sum(student):
return student["korean"] + student["math"] + student["english"] + student["science"]
def student_get_average(student):
return student_get_sum(student) / 4
def student_to_string(student):
return "{}\t{}\t{}".format(student["name"], student_get_sum(student), student_get_average(student))
# 학생 리스트 선언
students = [
create_student("윤인성", 87, 98, 88, 95),
create_student("연하진", 92, 98, 96, 98),
create_student("구지연", 76, 96, 94, 90),
create_student("나선주", 98, 92, 96, 92),
create_student("윤아린", 95, 98, 98, 98),
create_student("윤명원", 64, 88, 92, 92)
]
# 학생 한 명씩 반복
print("이름", "총점", "평균", sep="\t")
for student in students:
# 출력
print(student_to_string(student))
🖥️ 결과
class 클래스 이름:
클래스 내용
📖 인스턴스(instance)
- 클래스 기반으로 만들어진 객체.
인스턴스 이름/변수 이름 = 클래스 이름() # 생성자 함수
class 클래스 이름:
def __init__(self, 추가적인 매개변수):
pass
⌨️ 위의 코드에서 생성자 이용해 함수 구현
# 클래스 선언
class Student:
def __init__(self, name, korean, math, english, science):
self.name = name
self.korean = korean
self.math = math
self.english = english
self.science = science
# 학생 리스트 선언
students = [
Student("윤인성", 87, 98, 88, 95),
Student("연하진", 92, 98, 96, 98),
Student("구지연", 76, 96, 94, 90),
Student("나선주", 98, 92, 96, 92),
Student("윤아린", 95, 98, 98, 98),
Student("윤명원", 64, 88, 92, 92)
]
# Student 인스턴스의 속성에 접근하는 방법
print(students[0].name)
print(students[0].korean)
print(students[0].math)
print(students[0].english)
print(students[0].science)
🖥️ 결과
class 클래스 이름:
def 메소드 이름(self, 추가적인 매개변수):
pass
⌨️ 위의 함수에서 함수(메소드) 선언하기
# 클래스 선언
class Student:
def __init__(self, name, korean, math, english, science):
self.name = name
self.korean = korean
self.math = math
self.english = english
self.science = science
def get_sum(self):
return self.korean + self.math + self.english + self.science
def get_average(self):
return self.get_sum() / 4
def to_string(self):
return "{}\t{}\t{}".format(\
self.name,\
self.get_sum(),\
self.get_average())
# 학생 리스트 선언
students = [
Student("윤인성", 87, 98, 88, 95),
Student("연하진", 92, 98, 96, 98),
Student("구지연", 76, 96, 94, 90),
Student("나선주", 98, 92, 96, 92),
Student("윤아린", 95, 98, 98, 98),
Student("윤명원", 64, 88, 92, 92)
]
# 학생 한 명씩 반복
print("이름", "총점", "평균", sep="\t")
for student in students:
# 출력
print(student.to_string())
🖥️ 결과
📖 isinstance() 함수
- 객체(인스턴스)가 어떤 클래스로부터 만들어졌는지 확인 가능.
- 클래스 간 상속 관계까지 확인.
- 하나의 리스트로 여러 종류 데이터 처리 가능.
- 첫 번째 매개변수 : 객체(인스턴스), 두 번째 매개변수 : 클래스
isinstance(인스턴스, 클래스)
⌨️ 클래스 확인 예제
# 클래스 선언
class Student:
def __init__(self):
pass
# 학생 선언
student = Student()
# 인스턴스 확인 방법 1
print("isinstance(student, Student):",isinstance(student, Student))
# 인스턴스 확인 방법 2
type(student) == Student # 상속 사용 관계는 확인하지 않음
🖥️ 결과
📖 특수 메소드
- 파이썬이 클래스 사용 시, 제공해주는 보조 기능.
- 특수 상황에 자동 호출됨.
- 형태
__<이름>__()
❗️ 원하는 함수 이름을 사용하면 안되는 이유
- 프로그래밍할 때는 항상 다른 사람과의 협업 관점에서 함수를 사용해야 하기
때문!
✅ 클래스 변수
- 만드는 방법 : class 구문 바로 아래 단계에 변수 선언.
- 클래스 변수 만들기
class 클래스 이름: 클래스 변수 = 값
- 클래스 변수에 접근하기
클래스 이름.변수 이름
✅ 클래스 함수
- 만드는 방법
- 일반 함수 만들기와 비슷.
- 첫 번째 매개변수 : 클래스 자체. cls란 이름의 변수로 선언.
- '클래스가 가진 기능'이라고 명시적으로 나타냄.
- 클래스 함수 만들기
class 클래스 이름: @classmethod def 클래스 함수(cls, 매개변수): pass
- 클래스 함수 호출
클래스 이름.함수 이름(매개변수)
📖 가비지 컬렉터
- 더 사용할 가능성 없는 데이터를 메모리에서 제거.
- 변수에 저장되지 않는 경우.
- 함수 등에서 나오면서 변수 활용할 수 없는 경우.
- 스왑(swap)
- 메모리가 부족할 때 컴퓨터가 하드디스크를 메모리처럼 사용해 올리는 것.
- 하드디스크 : 메모리보다 매우 느려 스왑 처리 속도 매우 느림.
- 알아서 잘 작동.
📖 프라이빗 변수
- 변수 마음대로 사용하는 것 방지.
- 언더바 2개 붙이기만 하면 외부에서 사용할 수 없는 변수가 됨.
인스턴스 변수 이름 → '__<변수 이름>' 형태로 선언.
- 게더(getter), 세터(setter)
- 프라이빗 변수 값 추출 또는 변경 목적.
- 간접적 속성 접근 가능하게 해주는 함수.
- 데코레이터 사용해 쉽게 만들기 가능.
# 데코레이터 추가 @ property # 변수 이름과 같은 함수 정의. @ <변수 이름>.setter
📖 상속
- 다른 이가 만들어 놓은 기본 형태에 원하는 것만 교체하는 것.
- 부모(parent) : 기반이 되는 것 → 자식에게 자신의 기반 물려줌.
- 자식(child) : 기반으로 생성한 것.- 다중 상속
- 다른 이가 만들어 놓은 형태들을 조립해 원하는 것 만드는 것.
- 거의 사용 X- 클래스 기반 객체 지향 언어들이 지원하는 기능.
⌨️ 상속
# 부모 클래스 선언
class Parent:
def __init__(self):
self.value = "테스트"
print("Parent 클래스의 __init()__ 메소드가 호출되었습니다.")
def test(self):
print("Parent 클래스의 test() 메소드입니다.")
# 자식 클래스 선언
class Child(Parent):
def __init__(self):
Parent.__init__(self)
print("Child 클래스의 __init()__ 메소드가 호출되었습니다.")
# 자식 클래스의 인스턴스를 생성하고 부모 메소드 호출
child = Child()
child.test()
print(child.value)
🖥️ 결과
⌨️ 사용자 정의 예외 클래스
class CustomException(Exception):
def __init__(self):
Exception.__init__(self)
raise CustomException
🖥️ 결과
📖 재정의/오버라이드(override)
- 부모에 정의되어 있는 함수를 자식에서 다시 정의하는 것.
- 코드 실행하면 출력 약간 변화.
⌨️ 자식 클래스로써 부모 함수 재정의
class CustomException(Exception):
def __init__(self):
Exception.__init__(self)
print("### 내가 만든 오류가 생성되었어요! ###")
def __str__(self):
return "오류가 발생했어요"
raise CustomException
🖥️ 결과
⌨️ 자식 클래스로써 새로운 함수 정의
class CustomException(Exception):
def __init__(self, message, value):
Exception.__init__(self)
self.message = message
self.value = value
def __str__(self):
return self.message
def print(self):
print("### 오류 정보 ###")
print("메세지:", self.message)
print("값:", self.value)
# 예외 발생
try:
raise CustomException("딱히 이유 없음", 777)
except CustomException as e:
e.print()
🖥️ 결과