1. 매개변수
기본적으로 주로 사용하는 형식은 위치 매개변수를 사용하는 함수 형식이다.
### 위치 매개변수를 사용하는 함수
def function1(a,b):
print(a,b)
function1(1,2)
1,2
기본값을 주는 경우는 모든 매개변수를 기본값 정의 형식으로 사용하거나 제일 뒤의 값을 기본값 정의 형식으로 사용하는 경우에는 오류가 나지 않지만 앞은 기본값을 주고 뒤의 값은 나중에 인자를 넣어주려고 하면 오류가 발생한다.
### 기본값(default) 정의 매개변수를 사용하는 함수
# 앞은 기본값 주고 뒤에는 기본값 안주면 오류남
def function2(a,b=3):
print(a,b)
function2(2)
2,3
### 키워드 정의 방식
def function3(a,b):
print(a,b)
function3(a=1,b=2)
function3(b=5,a=4)
1 2
4 5
가변형 매개변수를 배우기 위한 빌드업이었다
args는 거의 공통으로 사용하는 변수이므로 바꿀 수 있다
중요한 것은 * 의 개수!
* 이 하나일 때와 두개일 때를 구분해서 튜플형태, 딕셔너리 형태의 값을 저장하고자 할 때 사용하면 된다
### 가변형 매개변수를 사용하는 함수
# 전달할 값이 몇개일지 모르는 상황에서 사용하는 방식 (튜플 형식 )
def function4(*args):
print(args)
function4(1,2,3,4,5)
function4(1,2)
(1, 2, 3, 4, 5)
(1, 2)
### 가변 키워드 매개변수를 사용하는 함수
# 전달할 값이 몇개일지 모르는 상황에서 사용하는 방식 (딕셔너리 형식 )
def function5(**args):
print(args)
function5(a = 1, b = 2, c = 3)
dic = {"a" : 33, "b" : 55}
# function5(a=33,b=55) 이와 같이 넣어짐 아래는 가변형 키워드 사용
function5(**dic)
{'a': 1, 'b': 2, 'c': 3}
{'a': 33, 'b': 55}
2.데코레이터
<데코레이터(Decorator)>
- 함수의 재사용성을 확장한 개념의 방법
- 공통적으로 사용되는것 (exe_function) 에 특정기능(wrapper)를 사용하고 싶을때 주로 사용
<함수 실행 시간 확인하는 데코레이터 프로그램 작성>
import time
### 데코레이터 함수 정의하기
# func : 실제 처리할 함수 받아오는 매개변수
def timer_decorator(func):
print(f"#1 : func = {func}")
###실제 실행될 함수 정의 (함수 이름은 자유롭게)
# func로 받은 함수를 아래 함수로 재정의하게 됨
def wrapper(*args,**kwargs): # *args : 변수의 개수 **kwargs : 딕셔너리 튜플등의 개수
# 시작시간
start_time = time.time()
print(f"#2 : start_time = {start_time}")
### 실제 처리할 함수 : func
rs = func(*args,**kwargs)
print(f"#3 : rs = {rs}")
# 종료시간
end_time = time.time()
print(f"#4 : end_time = {end_time}")
return rs
print('#5------------')
return wrapper
### 데코레이터 호출 및 처리할 함수 정의하기
# 데코레이터 호출은 @ 를 사용함
# 데코레이터 함수 호출시 밑에 정의된 함수 exe_function이 자동으로 매개변수로 전달됨(func)
# 데코레이터 함수가 리턴한 wrapper 함수는 exe_function이 된다.
# -> 재정의 되는 시점
@timer_decorator
def exe_function():
print("실제 처리할 함수")
### 2초간 대기 : 데코레이터가 처리되는 시간을 벌어주기 위해서
time.sleep(2)
#1 : func = <function exe_function at 0x000001B59BFB1E40>
#5------------
### exe_function 호출 -> wrapper로 재정의 되어 실제로는 wrapper가 실행됨
exe_function()
#2 : start_time = 1699930920.1654737 실제 처리할 함수
#3 : rs = None
#4 : end_time = 1699930922.1656325
<로그 데코레이터>
def log_decorator(func):
print(f"#1 : func = {func}")
def wrapper(*args,**kwargs):
print(f"Logo : {func.__name__}함수 호출됨")
rs = func(*args,**kwargs)
print(f"Logo : {func.__name__}함수 종료됨")
return rs
print("#2--------")
return wrapper
### 데코레이터 호출 및 처리함수 정의
@log_decorator
def another_function():
print("여긴 어디? 넌 누구?")
#1 : func = <function another_function at 0x000001B59C0AEC00>
#2--------
### 처리함수 호출
another_function()
Logo : another_function함수 호출됨
여긴 어디? 넌 누구?
Logo : another_function함수 종료됨
<데코레이터 내부함수에서 처리된 결과를 받아보기>
def check_permission(param_id):
print(f"#1 : param_id = {param_id}")
def decorator(func):
print(f"#2 : func= {func}")
def wrapper(*args , **kwargs):
check_id = "admin"
print(f"#3 : check_id = {check_id}")
if check_id == param_id:
args = ["인증성공"]
print(f"#4 : args = {args}")
return func(*args , **kwargs)
else:
print(f"#5 : raise 명령으로 강제 오류 발생 시킴 -----")
raise PermissionError("접근불가")
print("#6 : --------------")
return wrapper
print("#7 : --------------")
return decorator
###데코레이터 호출 및 처리함수 정의
@check_permission(param_id = "admin")
def admin_function(rs_msg) :
print(f"인증결과 : {rs_msg}")
#1 : param_id = admin
#7 : --------------
#2 : func= <function admin_function at 0x000001B59CCD56C0>
#6 : --------------
###처리함수 호출
admin_function()
#3 : check_id = admin
#4 : args = ['인증성공']
인증결과 : 인증성공
<영문 소문자 2개를 매개변수로 받아서, 대문자로 변환하는 데코레이터 프로그램>
### 함수이름 자유롭게 생성
# - 데코레이터 함수 생성해서 대문자로 출력까지
def upper_decorator(func):
### 인자로 넘어온 2개의 소문자는 args 매개변수가 받게됨
def wrapper(*args ,**kwargs):
### 인자로 넘겨받은 2개의 소문자를 대문자로 처리하는 영역
args =[arg.upper() for arg in args]
### 대문자로 변환된 값 2개를 args에 리스트 타입으로 담아서 넘기면 됨
return func(*args,**kwargs)
return wrapper
### 데코레이터 호출 및 처리 함수 정의
@upper_decorator
def upper_function(param1 , param2):
print(f"대문자로 변환된 {param1} / {param2}")
### 처리하는 함수 호출 : 소문자 2개를 인자로 넘겨주기
upper_function("abcd","efgh")
대문자로 변환된 ABCD / EFGH
<실습> 어제 작성한 도서관리 프로그램에 데코레이터를 적용해서 해주세요
### 기능을 수행할 클래스(모듈 or 라이브러리) 정의
class LibraryKiosk :
### 클래스 생성자 정의
def __init__(self) :
### 도서 목록을 저장할 딕셔너리 변수 생성
# - 도서번호, 도서제목, 도서재고수량 정보 담기
self.books = {}
print("클래스 생성 되었습니다.")
### 도서 입고 데코레이터 함수 정의하기
def add_book_decorator(func):
def wrapper(self, book_id, title, quantity):
func(self, book_id, title, quantity)
return wrapper
@add_book_decorator
def add_book(self, book_id, title, quantity):
if book_id in self.books:
self.books[book_id]["quantity"] += quantity
else :
self.books[book_id] = {"title":title,"quantity":quantity}
print(f"도서번호:{book_id} / 제목:{title} / 입고수량:{quantity} 입고 성공!!")
def borrow_book_decorator(func):
def wrapper(self, book_id):
func(self, book_id)
return wrapper
@borrow_book_decorator
def borrow_book(self, book_id):
if (book_id in self.books) and (self.books[book_id]["quantity"] > 0) :
self.books[book_id]["quantity"] -= 1
print(f"도서번호:{book_id} / 제목:{self.books[book_id]['title']} / 남은재고수량:{self.books[book_id]['quantity']}")
else :
print("도서가 존재하지 않거나, 대출할 재고가 없습니다.")
def return_book_decorator(func):
def wrapper(self, book_id):
func(self, book_id)
return wrapper
@return_book_decorator
def return_book(self, book_id):
if book_id in self.books :
self.books[book_id]["quantity"] += 1
print(f"도서번호:{book_id} / 제목:{self.books[book_id]['title']} / 남은재고수량:{self.books[book_id]['quantity']}")
else :
print("해당 도서가 존재하지 않습니다.")
### 2. 최초에 실행할 기능(함수) 정의
def main() :
### 클래스 생성하기
# - 최초 한번 : 프로그램이 종료되면 클래스는 소멸(메모리 공간 삭제)됩니다.
kiosk = LibraryKiosk()
print(kiosk)
#print("main 함수 호출!!")
### 3. 메뉴 선택 보여주기
while True :
print("<도서 키오스크 메뉴>")
print("1. 도서 입고")
print("2. 도서 대출")
print("3. 도서 반납")
print("4. 종료")
choice = input("원하는 번호(1~4)를 선택하세요 : ")
if choice == "1" :
#print("입고 선택")
book_id = input("도서 번호를 입력해 주세요 : ")
title = input("도서 제목를 입력해 주세요 : ")
quantity= int(input("입고할 권수를 입력해 주세요 : "))
#print(f"{book_id} / {title} / {quantity}")
# - 클래스 내부의 입고 기능 호출하기
kiosk.add_book(book_id, title, quantity)
elif choice == "2" :
#print("대출 선택")
book_id = input("대출할 도서번호를 입력해주세요 : ")
### 클래스 내부의 대출 기능 호출하기
kiosk.borrow_book(book_id)
elif choice == "3" :
#print("반납 선택")
book_id = input("반납할 도서번호를 입력해주세요 : ")
### 클래스 내부의 반납 기능 호출하기
kiosk.return_book(book_id)
elif choice == "4" :
print("종료 선택")
break
else :
print("잘못 선택...다시 선택해 주세요!!")
### 1. 최초 코드 시작
if __name__ == "__main__" :
### 최초에 실행할 기능(함수) 호출
main()
클래스 생성 되었습니다.
<__main__.LibraryKiosk object at 0x000001DE3A55BFD0>
<도서 키오스크 메뉴>
1. 도서 입고
2. 도서 대출
3. 도서 반납
4. 종료
원하는 번호(1~4)를 선택하세요 : 1
도서 번호를 입력해 주세요 : 1
도서 제목를 입력해 주세요 : 해리포터
입고할 권수를 입력해 주세요 : 3
도서번호:1 / 제목:해리포터 / 입고수량:3 입고 성공!!
데코레이터 사용법 : 데코레이터 생성 - 데코레이터 호출 및 처리함수 정의 - 처리함수 호출
실습 내용에서 데코레이터를 사용하려고하니 막막하게 느껴졌다
추가적으로 self, book_id, title, quantity 와 같은 부분을 가변형 매개변수 *args로 받아 사용할 수 있지 않을까 하고
실행해보았는데 self에서 오류가 발생하는 것을 알 수 있었다.
self, *args로 변경하니 입력시에 args 에 도서번호, 제목, 입고 권수가 ( '1' , '해리포터' , '3') 과 같이 튜플 형태로 저장되는 것을 알 수 있었다
그러나 book_id와 같이 key 값이 없는 형태라 book_id를 통해 기존에 있는 책인지를 판단하는 if문에서 오류가 발생하였다.
결국에는 원래처럼 위치 매개변수를 사용하여야할 것 같다.ㅎㅎ
'Python' 카테고리의 다른 글
Python 제너레이터(Generator) (0) | 2023.11.16 |
---|---|
Python 이터레이터(Iterator) (4) | 2023.11.16 |
Python 유니코드, 클로저 (5) | 2023.11.14 |
Python 11/08 (5) | 2023.11.08 |
List 내 for 문 (0) | 2023.11.07 |