# 함수 : 입력값(인자) -> 처리 -> 반환(여러 개가 올 수 있다!)

# python의 함수
# 두 개 이상의 값 리턴 가능
# 명시적 인자 호출
# 디폴트 인자
# 가변 인자
# 정의되지 않은 인자

# 정의 및 선언 방법
# def 함수명( 인자..... ):
# doing something
# return

def hello():
    print('hello')
    print('fn')
hello()  # 호출

def add(a, b):
    return a + b

rst = add(1, 3)
print(rst)

# 리턴값이 여러 개인 함수 
def fn1():
    return 10, 20, 30

# 선언 방법 1 : tuple
rst1 = fn1()    # 자동을 tuple로 변환이 된다.
print(rst1)

# 선언 방법 2 : 각각의 리턴 값을 따로 받아둔다
a, b, c = fn1()
print(a)
print(b)
print(c)
# 명시적 인자 호출
def fn(a, b):
    print(a, b)

fn(10, 20)

fn(b = 400, a = 300)    # 인자가 들어가는 파라미터를 명시적으로 정해준다

# print()의 명시적 인자 호출
n = 10
m = 100
print(n, m, sep='-')    # print()의 seperator 인자를 명시적으로 호출하여 수정한다(default는 ' '임)

print('hello')
print('hi')

print('hello', end=' ') # print()의 end 인자를 명시적으로 호출하여 수정한다(default는 '\\n'임)
print('hi')

# 함수의 default 인자
def func(a = 10, b = 20, c = 30):
    print(a, b, c)

func()
func(100)
func(100, 200)
func(100, 200, 300)

func(b = 1000)  # 명시적 인자 호출

# 가변 인자 : 인자의 개수가 정해져있지 않다
def func1(*args):   # 가변인자
    print(args)     # 넘어온 인자 값은 튜플로 출력된다(args -> 튜플 타입)
    for n in args:  # 리턴 값 각각의 요소 출력
        print(n)
# 인자의 개수도 한정되어있지 않고, 타입 역시 마찬가지다.
func1(10, 20)   # (10, 20) : 튜플로 출력된다.
func1(10, 20, 30)
func1('aa', 'bb', 'cc', 'dd')

# 입력받은 원의 지름 각각에 대한 원의 면적
def area_of_circle(*radius):
    for n in radius:
        print('radius : ', n, 'area : ', ((n ** 2) / 2) * 3.14)
    print(type(radius)) # 튜플 타입
area_of_circle(3, 4, 5)

# 정의되지 않은 인자 : 인자의 개수 정해지지 않음. "변수명 = 값"의 형태로 호출해야 한다(명시적 인자 호출과 유사)
def func2(**args):
    print(args)
    print(type(args))   # dictionary 타입으로 호출됨
func2(name = 'John', age = 30)
func2(aa= 100, bb = 200, cc = 300)