[천재교육] 프로젝트 기반 빅데이터 서비스 개발자 양성 과정 9기
학습일 : 2024.08.08
📕 학습 목록
- 파이썬 문법 (*args / **kwargs, 데코레이터)
- 프레임워크 (Flask)
📗 기억할 내용
1) 파이썬 문법
① *args / **kwargs
- at 파이썬, 파라미터를 나타내는 구문
*args
- 위치 인수의 튜플을 함수에 전달
- 함수 호출 시 전달된 모든 위치 인수들을 하나의 튜플로 묶어줌
**kwargs
- 키워드 인수의 딕셔너리를 함수에 전달
- 함수 호출 시 전달된 모든 키워드 인수들을 하나의 딕셔너리로 묶어줌
*args / **kwargs 결합 사용
- 두 가지를 함께 사용; 위치 인수 / 키워드 인수 모두 받을 수 있음
# (1) *args 예시
# add_numbers() : 여러 개의 숫자를 받아 그 합계를 계산하는 사용자 정의 함수
# args : 가변 개수의 숫자 인수(튜플)
def add_numbers(*args):
print(f"args: {args}") # 인수를 튜플로 출력
total = sum(args) # args의 모든 숫자를 더함
return total
# 함수 호출
print(add_numbers(1, 2, 3))
'''
args: (1, 2, 3)
6
'''
print(add_numbers(10, 20, 30, 40))
'''
args: (10, 20, 30, 40)
100
'''
# (2) **kwargs 예시
# print_user_info() : 사용자 정보를 받아 출력하는 사용자 정의 함수
# kwargs : 가변 개수의 키워드 인수(딕셔너리)
def print_user_info(**kwargs):
print(f"kwargs: {kwargs}") # 인수를 딕셔너리로 출력
for key, value in kwargs.items(): # .items() : 딕셔너리의 키-값을 한쌍의 튜플로 반환 (key, value)
print(f"{key}: {value}")
# 함수 호출
print_user_info(name="Alice", age=30, city="New York")
'''
kwargs: {'name': 'Alice', 'age': 30, 'city': 'New York'} # 함수에 전달된 키워드 인수들이 딕셔너리로 변환됨
name: Alice
age: 30
city: New York
'''
# (3) *args / **kwargs 결합 사용
# describe_pet() : 반려동물의 이름, 다양한 특성, 추가 정보를 출력하는 사용자 정의 함수
# pet_name : '애완동물 이름' 인수
# args : '애완동물 특성' 가변 위치 인수
# kwargs : '추가 정보' 가변 키워드 인수
def describe_pet(pet_name, *args, **kwargs):
print(f"Pet Name: {pet_name}")
# 특성 출력
if args:
print("Features:")
for feature in args:
print(f" - {feature}")
# 추가 정보 출력
if kwargs:
print("Additional Info:")
for key, value in kwargs.items():
print(f" - {key}: {value}")
# 함수 호출
describe_pet("GamDong", "Cute", "Lovely", bread="Poodle", age=5)
'''
Pet Name: GamDong
Features:
- Cute
- Lovely
Additional Info:
- bread: Poodle
- age : 5
'''
② 데코레이터
- 다른 함수를 인수로 받아 새로운 함수를 반환하는 함수
- 기존 함수에 추가적인 기능을 부여
- 코드의 반복을 줄임; 깔끔
# [데코레이터 함수 예제]
# 함수를 인수로 받는 데코레이터 함수
def my_decorator(func): # say_hello 함수를 인수로 받아 wrapper 함수를 반환
def wrapper():
print("함수 호출 전 작업")
func()
print("함수 호출 후 작업")
return wrapper # my_decorator 함수는 wrapper 함수를 반환; 데코레이터가 실제로 동작하게 함
# 데코레이터 적용
@my_decorator # say_hello 함수가 my_decorator 에 의해 장식됨
def say_hello():
print("안녕하세요!")
say_hello() # say_hello 함수 호출시, 실제로는 wrapper 함수가 호출됨
'''
함수 호출 전 작업
안녕하세요!
함수 호출 후 작업
'''
[작동 순서]
1. say_hello() 함수 호출
2. @데코레이터에 의해, say_hello() 함수가 my_decorator() 함수의 인수로 들어감; func 자리에 옴
3. inner 함수 실행하다가, func() 차례에서 say_hello() 함수 실행
4. 다시 남은 inner 함수 실행
# [매개변수를 가진 함수와 함께 사용]
def my_decorator(func):
def wrapper(*args, **kwargs):
print("함수 호출 전 작업")
result = func(*args, **kwargs)
print("함수 호출 후 작업")
return result
return wrapper # 반환을 안해주면 my_decorator 함수는 wrapper 함수를 정의만 하고 끝남
@my_decorator
def greet(name):
print(f"안녕하세요, {name}님!")
greet("철수")
'''
함수 호출 전 작업
안녕하세요, 철수님!
함수 호출 후 작업
'''
# [데코레이터 체이닝] : 여러 데코레이터를 하나의 함수에 적용. 데코레이터는 위 → 아래로 적용됨
def decorator1(func)
def wrapper():
print("데코레이터 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("데코레이터 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("안녕하세요!")
say_hello()
'''
데코레이터1
데코레이터2
안녕하세요!
'''
2) 프레임워크
① 라이브러리 vs 프레임워크
- 라이브러리 (Library)
라이브러리 : 특정 기능을 수행하기 위해 사용자가 호출하는 도구 • 함수들의 집합
- 단순한 기능을 제공
- 개발자가 원하는 라이브러리를 호출하여 사용
- 프레임워크 (Framework)
프레임워크 : 애플리케이션의 구조와 흐름을 제어하기 위해, 사용자가 작성할 코드의 전체적인 구조를 정해둔 것
- 개발 전체를 진행하는 뼈대 • 기반 구조
- 개발에 대한 전체적인 흐름을 주도
- 프레임워크가 정해준대로 개발자가 개발을 진행
- 프레임워크 내부에 기능구현을 위한 라이브러리 • 코드들 내장
② Flask
- 플라스크 : 파이썬으로 작성된 마이크로 웹 프레임워크 * 마이크로 : 특정 도구 • 라이브러리를 강요하지 x
- 웹 애플리케이션을 구축하는 데 필요한 핵심 기능을 제공
# [1. Flask 설치]
pip install flask
# [2.Flask 모듈 호출]
# Flask : Flask 애플리케이션을 생성
# request : 클라이언트의 요청 데이터를 다룸
# render_template : HTML 파일을 렌더링 * 렌더링 : 서버가 클라이언트에게 보낼 HTML 페이지를 생성하는 과정.이때 사용되는 것이 템플릿(템플릿:미리 작성된 HTML 파일)
from flask import Flask, request, render_template
# [3. Flask 애플리케이션 생성]
# __name__ : 현재 모듈의 이름을 애플리케이션의 인자로 전달 → Flask 애플리케이션 인스턴스 생성
app = Flask(__name__)
# [4. 홈 페이지 경로 설정]
# 웹 서버가 특정 url 경로에 대해 어떤 기능을 수행할지 정의
@app.route('/') # 기본 경로('/')로 들어오는 요청을 처리하는 함수; 기본 경로에 대한 route를 설정 * route : url(클라이언트's 요청) - 함수(서버's 처리 로직)를 연결
def home(): # 기본 경로에 접근할 때 실행되는 사용자 정의 함수
return render_template('home.html') # home.html 템플릿을 렌더링 → 반환
# [5. 인사말 페이지로 경로 설정]
@app.route('/greet', methods=['POST']) # '/greet' 경로에 대한 POST 요청을 처리하는 route를 설정
def greet(): # '/greet' 경로에 접근할 때 실행되는 사용자 정의 함수
name = request.form['name'] # 폼 데이터에서 'name' 값을 호출
return render_template('greet.html', name=name) # greet.html 템플릿 렌더링 → name 값을 템플릿에 전달
# [6. 애플리케이션 실행]
if __name__ == '__main__': # 이 코드가 직접 실행될 때만 Flask 애플리케이션을 실행 # 기본 포트 : 5000번
app.run(debug=True) # 애플리케이션 실행 # debug=True : 디버그 모드 활성화; 코드 변경시 자동으로 서버가 재시작 & 오류 발생시 디버그 정보 표시
# [7-1. 템플릿 파일(templates/home.html) 만들기]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<h1>Welcome to the Home Page</h1>
<form action="/greet" method="post">
<!-- 사용자로부터 이름을 입력받는 폼 -->
<label for="name">Enter your name:</label>
<input type="text" id="name" name="name" required>
<button type="submit">Submit</button>
</form>
</body>
</html>
# [7-2. 템플릿 파일(templates/greet.html) 만들기]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Greeting</title>
</head>
<body>
<!-- 사용자 이름을 표시하는 인사말 페이지 -->
<h1>Hello, {{ name }}!</h1>
<a href="/">Go back to Home</a>
</body>
</html>
- 용어 설명
용어 | 설명 | 사용 예 |
app = Flask(__name__) | - 현재 스크립트를 기반으로 Flask 애플리케이션 인스턴스 생성 → 이 인스턴스를 app이라는 변수에 할당 - 추후 이 app 변수를 사용하여 웹 애플리케이션의 다양한 기능 정의•실행 |
|
Flask | - Flask 프레임워크의 핵심 클래스 - 추후 이 클래스를 통해 Flask 애플리케이션 인스턴스 생성 |
|
인스턴스 | - 웹 애플리케이션 그 자체 | |
app | - Flask 애플리케이션 인스턴스를 저장하는 변수 - 추후 이 app 변수를 통해 route 설정 & 서버 실행 |
|
__name__ | - 파이썬의 내장 변수; 모듈(스크립트)의 이름을 나타냄 - Flask는 '__name__' 값을 통해 애플리케이션의 위치를 결정 - 템플릿파일/정적파일의 위치를 찾을 때 '__name__'을 기반으로 기본 경로 설정 |
- 스크립트를 직접 실행하고 있다면; '__name__' → '__main__' 으로 받음 - 다른 스크립트에서 해당 스크립트를 import 했다면; '__name__' → '그 모듈의 이름(파일명)' 으로 받음 |
템플릿(template) 파일 | - 동적으로 내용을 생성하기 위한 HTML 파일 - 보통 Jinja2라는 템플릿 엔진을 사용하여 Flask 에서 동적 웹페이지를 생성할 때 사용됨 - templates 폴더 안에 위치 |
- 클라이언트가 http://example.com/ 라는 URL 에 접근했을 때, 어떤 HTML 페이지를 보여줄 지 • 데이터를 처리할지 결정 |
정적(static) 파일 | - 웹페이지 동작에 필요한 이미지/CSS/Javascript 같은 변하지 않는 파일 - static 폴더 안에 위치 |
|
라우트(route) | - 특정 URL에 대한 요청이 들어왔을 때, 실행할 함수를 연결하는 것 - 'URL - 그 URL로 요청이 들어왔을 때 실행될 함수' 를 연결해줌 |
|
@app.route() 데코레이터 | - 'URL 경로(route) - 데코레이터 아래에 있는 함수' 연결 - 그 함수가 해당 URL로 들어오는 요청을 처리 |
|
동적 라우팅 | - URL의 일부를 변수로 처리; 다양한 입력에 대응 | |
HTTP 메서드 | - GET, POST - 클라이언트(웹 브라우저)가 서버와 통신할 때, 요청의 성격을 지정 |
|
GET | - 데이터 조회 - 클라이언트가 서버로부터 데이터를 요청할 때 사용 - 웹페이지를 요청 • 서버에서 특정 정보를 받아옴 |
|
POST | - 데이터 제출 / 서버 상태 변경 - 클라이언트가 서버에 데이터를 전송할 때 사용 |
- 폼 데이터를 서버로 제출 - 서버의 상태 • 데이터를 변경 |
📘 트러블 슈팅
[문제]
- 문제 내용
출력 과정에서 오류 발생
name = "홍길동" age = 20 print("안녕하세요," + name "님, 당신의 나이는 " + age + "세입니다.")
{ "name": "TypeError", "message": "can only concatenate str (not \"int\") to str", "stack": "--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[2], line 3 1 name = \"홍길동\" 2 age = 20 ----> 3 print(\"안녕하세요,\" + name + \"님, 당신의 나이는 \" + age + \"세입니다.\") TypeError: can only concatenate str (not \"int\") to str" }
- 문제 원인
1종류 이상의 자료형을 한 문장으로 출력하려면; 산술연산자(+)가 아닌 쉼표(,)로 연결
[해결]
- 해결 방법
print("문자열", 변수, "문자열", 변수, "문자열") 의 형태로 출력
- 해결 결과
name = "홍길동" age = 20 print("안녕하세요, ", name, "님, 당신의 나이는 ", age, "세입니다.")
안녕하세요, 홍길동 님, 당신의 나이는 20 세입니다.
📙 내일 일정
- 파이썬 프로그래밍(컨테이너 자료형, 조건문, ...) 학습
'TIL _Today I Learned > 2024.08' 카테고리의 다른 글
[DAY 23] Django 웹 애플리케이션 개발 (0) | 2024.08.12 |
---|---|
[DAY 22] Flask (0) | 2024.08.09 |
[DAY 20] SQL (0) | 2024.08.07 |
[DAY 19] API, DB, SQL (0) | 2024.08.06 |
[DAY 18] HTML, CSS, Javascript (0) | 2024.08.05 |