정확히 필요한 parameter 수와 그 구조를 알 수 없는 경우?
def buy_A_car(options):
print(f"다음 사양의 자동차를 구입하십니다:")
for option in options:
print(f"{option} : {options[option]}")
options = {"seat" : "가죽", "blackbox" : "최신"}
buy_A_car(options)
> 다음 사양의 자동차를 구입하십니다:
seat : 가죽
blackbox : 최신
하지만 parameter로 무조건 dictionary만 받아야한다는 제약조건이 생긴다.
아무값도 안넘겨주거나 String을 넘기면 오류 날 가능성이 높다
(아무 값이 없을 때에도 빈 배열로 넘겨줘야 할 판!)
이럴 때 사용할 수 있는게 keyworded variable length of arguments!
: 수가 정해지지 않고 유동적으로 변할 수 있는 keyword arguments
: parameter 앞에 별표 두개 붙이기 **
**kwargs
- argument 수를 유동적으로 (0~N) 넘겨줄 수 있다
- 미리 정해져있지 않기 때문에 원하는 keyword를 유동적으로 사용할 수 있다
- dictionary형태로 지정된다.
def buy_A_car(**kwargs): print(f"다음 사양의 자동차를 구입하십니다:") - for option in kwargs: print(f"{option} : {kwargs[option]}")
이렇게 선언된 함수는 다음과 같이 호출할 수 있다
buy_A_car(seat="가죽", blackbox="최신", tint="yes")
kwargs 파라미터는 dictionary형태로 함수에 전달되기 때문에
{'seat': '가죽', 'blackbox': '최신', 'tint': 'yes'}
함수의 body 내에서는 dictionary처럼 kwargs를 사용하면 된다.
keyword를 사용하지 않고 순서대로 값을 전달하는 방식은?
*args
- tuple로 변환되어 함수에 전달된다
둘 다를 섞을 수도 있는데,
이는 어떠한 형태와 수의 argument도 허용하기 위해서!
(parameter에 있어서 엄청 유동적인 함수가 되는 것!)
👇🏻👇🏻 내가 푼 코드
def sum_of_numbers(*args, **kwargs):
result = 0
if len(args) == 0:
return result
else:
for i in args:
result += i
return result
def what_is_my_full_name(**kwargs):
temp = dict(reversed(list((kwargs).items())))
print(temp)
name = ""
for arg in temp:
if "last_name" in temp or "first_name" in temp:
if "last_name" in temp and "first_name" in temp:
if arg == "last_name":
name += temp[arg]
if arg == "first_name":
name += " " + temp[arg]
elif "last_name" in temp and "first_name" not in temp:
if arg == "last_name":
name += temp[arg]
elif "last_name" not in temp and "first_name" in temp:
if arg == "first_name":
name += temp[arg]
else:
name = "Nobody"
if len(temp) == 0:
name = "Nobody"
return name
정말 지저분 + 이리저리 막기만 한 코드..ㅎㅎ
👇🏻👇🏻 다른 분 코드
def sum_of_numbers(*args):
return sum(args)
def what_is_my_full_name(**kwargs):
if "first_name" in kwargs.keys():
if "last_name" in kwargs.keys():
return kwargs["last_name"] + " " + kwargs["first_name"]
else:
return kwargs["first_name"]
else:
if "last_name" in kwargs.keys():
return kwargs["last_name"]
else:
return "Nobody"
*kwargs, args를 잘 활용해서 다시한번 공부해보자!
이미 전에 Function(2) 게시글에 정리했지만,
wecode notion 보고 다시한번 정리하기!
👆🏻 decorator에 대한 개념이 없어
하나도 이해하지 못한 채 풀던 나자신..(애잔)
nested function
- 중첩 함수
: 함수 안에 함수가 선언된 것!
: 상위 부모 함수 내에서만 호출될 수 있다
: 가독성, Closure 때문에 사용
def print_all_elements(list_of_things):
## 중첩함수 선언
def print_each_element(things):
for thing in things:
print(thing)
if len(list_of_things) > 0:
print_each_element(list_of_things)
else:
print("There is nothing!")
함수 내에 반복되는 코드가 있다면 중첩함수로 선언하여 가독성 높여주어야 한다
all_elements 함수 내에 each_elements 함수를 선언해두고,
필요에 따라서 내부 함수만 반복하도록 한 상황!
def parent_function():
def child_function():
print("this is a child function")
child_function()
parent_function()
> "this is a child function"
부모함수의 변수, 정보를 가두어 사용하기 위해 중첩함수를 사용하기도 한다
- 중첩 함수가 부모 함수의 변수나 정보를 중첩 함수 내에서 사용한다.
- 부모 함수는 리턴값으로 중첩 함수를 리턴한다.
- 부모 함수에서 리턴 했으므로 부모 함수의 변수는 직접적인 접근이 불가능 하지만 부모 함수가 리턴한 중첩 함수를 통해서 사용될 수 있다.
: factory 패턴 구현 시, 함수나 오브젝트 생성해 낼 때
설정값을 노출하지 않아서 수정이 불가능하도록 만들 때 사용!
def generate_power(base_number):
def nth_power(power):
return base_number ** power
return nth_power
calculate_power_of_two = generate_power(2)
calculate_power_of_two(7)
> 128
calculate_power_of_two(10)
> 1024
calculate_power_of_seven = generate_power(7)
calculate_power_of_seven(3)
> 343
calculate_power_of_seven(5)
> 16907
특정 숫자의 승을 구하는 함수인데
그때그때 설정되는 수의 승을 구하는 함수이다!
def calculate_power_of_two(power):
return 2 ** power
calculate_power_of_two(7)
> 128
calculate_power_of_two(10)
> 1024
혹은
def calculate_power(number, power):
return number ** power
calculate_power(2, 7)
> 128
를 사용하면 2의 승을 구하는 함수이지만
위와같이 중첩함수를 사용하면
매번 들어오는 parameter 숫자의 승을 구할 수 있다!
데코레이터 강의
데코레이터 라는 개념이 정말 이해가 잘 되지 않았는데, 해당 강의를 듣고 많이 도움이 되었다.
데코레이터란,
- 함수를 parameter로 받아서 작동하는 것!
- 클래스에서 메서드 만들 때 @로 시작하는 decorator들을 많이 사용한다고..
- @decorator를 붙여서 선언된 함수는
그 함수가 실행되기 전에 decorator역할의 함수가 먼저 실행되고, 그 후에 기존 함수가 실행되는 것!
: 함수를 수정하지 않은 상태에서 추가기능 구현할 때 사용된다고 한다!
👆🏻 함수 안에서 함수 만들고 return하기
도대체 decorator가 어떤 순서로 왜 진행이 되는지 궁금했는데
👇🏻👇🏻 아래 그림을 보고 좀 이해가 되었다
decorator를 붙여서 선언된 함수를 실행하면 해당 함수가 실행되기 전에
decorator로서 선언된 함수로 이동해서, 매개변수로 받은 호출할 함수를 돌리는 것!
그래서 decorator로서 선언된 함수 내부가 먼저 실행되고, (trace - wrapper)
그 뒤에 decorator를 선언한 함수가 호출되는 것!! (hello)