인프런 파이썬 입문 수업을 듣고 중요한 내용을 정리했습니다.
개인 공부 후 자료를 남기기 위한 목적이므로 내용 상에 오류가 있을 수 있습니다.
functions
- 기본 개념
# 기본 구조 def funciton_name(parameter): code funciton_name(argument) # 활용 예시 def first_func(w): print("Hello, ", w) word = "Goodboy" first_func(word) # 결과 : Hello, Goodboy def return_func(w1): value = "Hello, " + str(w1) return value x = return_func('Goodboy2') print(x) # 결과 : Hello, Goodboy2 # value = "Hello, " + str(w1) # return value # 이러한 두 줄의 코드를 아래의 간결한 코드로 대체할 수도 있다. # return "Hello, " + str(w1) def func_mul(x): y1 = x * 10 y2 = x * 20 y3 = x * 30 return y1, y2, y3 a, b, c = func_mul(10) print(a, b, c) # 결과 : 100, 200, 300 # 위와 같은 방법으로 y1, y2, y3의 변수들을 # return으로 동시에 반환할 수 있다.(다중반환 or 다중리턴) # a, b, c = func_mul(10) 코드는 언팩킹을 의미하며, # 위에서 y1, y2, y3으로 반환된 값을 각각 a, b, c에 풀어서 넣어준다. def func_mul2(x): y1 = x * 10 y2 = x * 20 y3 = x * 30 return (y1, y2, y3) q = func_mul2(20) print(type(q), q) # 결과 : <class 'tuple'> (200, 400, 600) # return (y1, y2, y3) 코드는 팩킹을 의미하며, # 튜플 형태로 y1, y2, y3 변수들을 묶어준다. # 이것이 print(q)의 결과가 튜플 형태인 이유이다. def func_mul3(x): y1 = x * 10 y2 = x * 20 y3 = x * 30 return [y1, y2, y3] p = func_mul3(30) print(type(p), p) # 결과 : <class 'list'> [300, 600, 900] # return [y1, y2, y3] 코드는 팩킹을 의미하며, # 리스트 형태로 y1, y2, y3 변수들을 묶어준다. # 이것이 print(p)의 결과가 리스트 형태인 이유이다. def func_mul4(x): y1 = x * 10 y2 = x * 20 y3 = x * 30 return {y1, y2, y3} r = func_mul4(40) print(type(r), r) # 결과 : <class 'set'> {400, 800, 1200} # return {y1, y2, y3} 코드는 팩킹을 의미하며, # 집합(set) 형태로 y1, y2, y3 변수들을 묶어준다. # 이것이 print(r)의 결과가 집합(set) 형태인 이유이다. def func_mul5(x): y1 = x * 10 y2 = x * 20 y3 = x * 30 return {'v1': y1, 'v2': y2, 'v3': y3} k = func_mul5(50) print(type(k), k) # 결과 : <class 'dict'> {'v1': 500, 'v2': 1000, 'v3': 1500} print(k.get('v2'), k.items(), k.keys()) # 결과 : # 1000 # dict_items([('v1', 500), ('v2', 1000), ('v3', 1500)]) # dict_keys(['v1', 'v2', 'v3']) # return {'v1': y1, 'v2': y2, 'v3': y3} 코드는 팩킹을 의미하며, # 딕셔너리 형태로 y1, y2, y3 변수들을 묶어준다. # 이것이 print(k)의 결과가 딕셔너리 형태인 이유이다.
- 응용 개념
# 언팩킹 # *args(튜플 자료형 언팩킹) def args_func(*args): for i, v in enumerate(args): print('Result : {}'.format(i), v) print('----------') args_func('Lee') args_func('Lee', 'Park') args_func('Lee', 'Park', 'Kim') # 결과 : # Result : 0 Lee # ---------- # Result : 0 Lee # Result : 1 Park # ---------- # Result : 0 Lee # Result : 1 Park # Result : 2 Kim # ---------- # args_func( ) 함수의 파라미터는 반드시 *args일 필요가 없으며, # 자유롭게 파라미터 이름을 넣어주면 된다.(ex : *a) # args_func( ) 함수의 파라미터로 *args를 넣으면, # 몇 개의 전달인자가 팩킹 형태로(묶여서) 파라미터로 들어오든 상관없이, # 하나씩 언팩킹하여(풀어서) 함수코드에 적용할 수 있다. # 즉, 튜플 형태의 전달인자가 파라미터로 들어오면 튜플의 데이터를 하나씩 언팩킹하여 # 함수 코드에 적용하는 것이다. # enumerate( ) 함수는 팩킹된 데이터의 인덱스 번호와 데이터 요소를 반복문에 # 적용하는 함수이다. # 즉, 파라미터 *args안에 튜플 형태의 전달인자가 들어왔기 때문에, # enumerate( ) 함수는 튜플의 인덱스 번호는 i에 넣어주고, 데이터 요소는 v에 넣어준다. # **kwargs(딕셔너리 자료형 언팩킹) def kwargs_func(**kwargs): for v in kwargs.keys(): print("{}".format(v), kwargs[v]) print('---------') kwargs_func(name1='Lee') kwargs_func(name1='Lee', name2='Park') kwargs_func(name1='Lee', name2='Park', name3='Kim') # 결과 : # name1 Lee # --------- # name1 Lee # name2 Park # --------- # name1 Lee # name2 Park # name3 Kim # --------- # 기본적으로 위의 *args 코드와 원리는 동일하다. # 단지 전달인자로 파라미터에 넘기는 자료형이 다를 뿐이다.(딕셔너리) # kwargs_func(name1='Lee')에서 name1은 키, Lee는 벨류이다. # 즉, 전달인자로 파라미터 **kwargs에 딕셔너리 형태의 데이터를 넘긴 것이다. # *args와 **kwargs의 활용 예시 def example(args_1, args_2, *args, **kwargs): print(args_1, args_2, args, kwargs) example(10, 20, 'Lee', 'Kim', 'Park', age1=20, age=20, age3=40) # 결과 : # 10 20 ('Lee', 'Kim', 'Park') {'age1': 20, 'age': 20, 'age3': 40} # 전달인자 10과 20은 파라미터 args_1과 args_2에 각각 할당되고, # 전달인자 'Lee', 'Kim', 'Park'는 파라미터 *args에 할당되어 튜플 형태로 출력된다. # 이 때 전달인자가 몇 개이든 상관없이 모두 튜플 형태로 묶여서 출력된다. # 또한, 키와 벨류로 구성된 전달인자 age1=20, age=20, age3=40는 # 파라미터 **kwargs에 할당되어, 딕셔너리 형태로 출력된다. # 마찬가지로 전달인자가 몇 개이든 상관없이 모두 딕셔너리 형태로 묶여서 출력된다. # 중첩함수 def nested_func(num): def func_in_func(num): print(num) print("In func") func_in_func(num + 100) nested_func(100) # 결과 : In func 200 # 중첩함수의 실행 원리는 다음과 같다. # 우선, nested_func( ) 함수를 전달인자 100을 넣어 호출하면, # nested_func( ) 함수 안에서 func_in_func( ) 함수가 새롭게 정의되고, # 동시에 print("In func") 코드와 func_in_func( ) 함수가 호출된다. # 이 때, nested_func( ) 함수의 전달인자인 100은 파라미터 num에 들어가고, # num에 들어간 100이 func_in_func( ) 함수가 호출되는 과정에서 # num + 100의 전달인자에 들어간다. # 즉, func_in_func( ) 함수는 전달인자 200을 갖고 호출되며, # 전달인자 200은 func_in_func( ) 함수의 파라미터로 들어가서, # print(num) 코드를 통해 출력되는 것이다. # 참고로 func_in_func( ) 함수를 nested_func( ) 함수 밖에서 # 호출하면 에러가 발생한다. # 그 이유는 nested_func( ) 함수를 호출해야만, func_in_func( ) 함수가 # 정의되기 때문이다. # 즉, nested_func( ) 함수의 호출 없이 독자적으로 func_in_func( ) 함수를 호출하면, # 정의되지 않은 함수를 호출하는 것과 동일하므로 에러가 발생하는 것이다. # lambda(람다식) # 람다식은 메모리를 절약하고, 코드가 간결하여 가독성이 향상된다는 장점이 있다. # 하지만 람다식을 너무 남발하는 경우에는 오히려 가독성이 떨어진다는 반론도 존재한다. # 일반함수는 객체를 생성하고 메모리에 할당되지만, # 람다식은 즉시실행 함수이기 때문에 Heap영역에 저장되고 메모리가 초기화되어, # 메모리를 효율적으로 사용한다는 차이점이 있다. # 기본 구조 # 일반함수의 구조 def mul_func(x, y): return x * y # 람다식의 구조 lambda x, y: x * y # 위의 코드와 동일한 기능을 람다식 코드로 구현한 것이다. # 람다식은 이름이 없기 때문에, 변수에 담아서 쓰거나 함수의 인자로 넘겨서 사용한다. # 활용 예시 # 예시1 # 일반함수 사용 예시 def mul_func(x, y): return x * y q = mul_func(10, 50) print(q) # 함수 호출방법1 print(mul_func(30, 50)) # 함수 호출방법2 mul_func_var = mul_func print(mul_func_var(20, 50)) # 함수 호출방법3 # 일반 함수는 함수명이 존재하기 때문에 객체를 생성하고 메모리에 할당되어 실행된다. # 람다식 사용 예시(동일한 기능 구현) lambda_mul_func = lambda x, y: x * y print(lambda_mul_func(50, 50)) # 람다식은 단순히 변수에 할당되어 곧 바로 실행된다.(함수명 존재X) # 예시2 # 일반함수 사용 예시 def mul_func(x, y): return x * y mul_func_var = mul_func def func_final(x, y, func): print(x * y * func(100, 100)) func_final(10, 20, mul_func_var) # 람다식 사용 예시(동일한 기능 구현) def func_final(x, y, func): print(x * y * func(100, 100)) func_final(10, 20, lambda x, y: x * y) # 이처럼 람다식은 일반함수를 정의하지 않고, 함수의 기능을 즉시 실행할 수 있다.
'Python' 카테고리의 다른 글
Python - class (0) | 2021.10.15 |
---|---|
Python - input (0) | 2021.10.15 |
Python - while문 (0) | 2021.10.14 |
Python - for문 (0) | 2021.10.14 |
Python - if문 (0) | 2021.10.14 |
댓글