본문 바로가기

파이썬 python

05 함수

함수

  • 어떠한 작업을 수행하기 위해 독립적으로 설계된 코드의 집합
  • 재사용할 코드 묶음

 

함수 정의 방법

  • 파라미터(parameter): 함수를 정의할 때 객체를 전달받는 변수(매개변수)
  • 아규먼트(argument): 함수를 실행하는 쪽에서 함수에 넣어주는 값(인수)
  • def <function_name>(parameter, ...):
        code context
        ... 
        return <value> # 생략 가능
  • 파라미터 정의와 `return`은 해도 되고 안해도 된다

 

>>> def get_std(num_list): # num_list 파라미터
>>>     avg = sum(num_list) / len(num_list) # 평균 , avg는 지역변수

>>>     deviation_list = []

>>>     for num in num_list:
>>>         deviation = avg - num
>>>         deviation_list.append(deviation**2)

>>>     var = sum(deviation_list) / len(deviation_list)
>>>     return var ** 0.5 

>>> num_list = [1,2,3,4,5,6]
>>> get_std(num_list)
1.707825127659933

>>> get_std([1,2,3,4,5,6])
1.707825127659933

 

 

#안되는 거
>>> get_std(num_list, num_list)
-> TypeError: get_std() takes 1 positional argument but 2 were given

>>> get_std()
-> TypeError: get_std() missing 1 required positional argument: 'num_list'

 

이름을 지을 때 관례 (Naming Rule)

  • 함수이름은 동사로 시작하며, 사용자 입장에서 어떠한 기능을 추측할 수 있게 해야한다.
  • 함수는 소문자로만 작성하며, snake case를 따른다. ( ex. `def add_number()` ) 
  • 함수의 파라미터와 지역변수 둘중에 하나는 lower camel case를 따른다. (ex. userName , userAge )

 

변수의 사용 범위 (scope)

  • local(지역변수): 함수 내부에 만들어진 지역 변수는 함수 내에서만 사용 가능 (파라미터도 동일!!)
  • global(전역변수): 함수 밖에서 만들어진 변수는 어디에서든 사용 가능
  • 함수내부에서 변수를 사용할 때는 지역변수로 선언하거나 파라미터로 받을것!!

 

안 좋은 예시

>>> gv = 10 # 전역변수

>>> def do_func():
>>>     print(gv) # 절대 이렇게 하지 마세요!!

>>> do_func()
10

 

이렇게 하기

>>> def do_func():
>>>     gv = 100 # 지역변수
>>>     print(gv)

>>> do_func()
100

>>> print(gv)
10

 

>>> def do_func():
>>>     loc = 10
>>>     print(loc)
>>> do_func()

>>> print(loc)
-> NameError: name 'loc' is not defined

#함수 내에서 지역변수를 전역변수로 변경하는 방법
>>> def do_func():
>>>     global gv_loc
>>>     gv_loc = 100

>>> do_func()

>>> gv_loc
100

 

함수에 아규먼트를 넣는 방식

>>> def do_func(a,b,c):
>>>     print(a,b,c)
    
#이렇게 전달 하는 방식을 positional argument 전달 방식    
>>> do_func(1,2,3) 
1 2 3

#이렇게 전달 하는 방식을 keyword argument 전달 방식
>>> do_func(a=1,b=2,c=3)
1 2 3

 

파라미터 정의하기

디폴트 파라미터

  • 아규먼트를 넣어주지 않을 때 파라미터에 지정된 초기값을 사용
>>> def do_func(a,b,c=1004):
>>>     print(a,b,c)
    
>>> do_func("hello",30)
hello 30 1004

 

다음의 리스트는 행과 열 형태로 구성되어 있다.
다음과 같은 행렬 형태의 리스트를 전달 받고,
추가로 열을 선택할 수 있는 정수를 전달 받아 열부분만 리스트에 담아 반환하는 함수를 만들어 주세요.

두번째 인수인 열부분을 선택할 수 있는 정수가 생략될 경우
0번째 열부분을 리스트에 담아 반환하면 됩니다.

lst = [[1,2,3], [4,5,6], [7,8,9]]

get_column(lst,1)

Output:
[2,5,8]

 

행열을 불러오는 함수

 

get_column
get_index

 

>>> lst = [
>>>     [1,2,3],
>>>     [4,5,6],
>>>     [7,8,9]
>>> ]

#i=1이니까 두번째 열
>>> def get_column(lst,i=1):
>>>     return [ n[i] for n in lst]

>>> get_column(lst)
[2, 5, 8]

 

가변 파라미터

  • 함수를 정의하면서 아규먼트가 0개이상 들어갈 수 있게 해주는 파라미터
  • *(asterisk)를 이용해서 정의하면 된다.
  • 일반적으로 `*args` 로 표현
  • 함수 내부에서는 튜플 형태로 묶임
>>> def do_func(*args):
>>>     print(args)
>>>     total = sum(args)
>>>     return total

>>> do_func(1,2)
(1, 2)

 

>>> def do_func(a,*args,b=100):
>>>     print(a)
>>>     print(args)
>>>     print(b)
    
>>> do_func(1,2,3,4,5,6,7,8,1000)    
1
(2, 3, 4, 5, 6, 7, 8, 1000)
100

# keyword argument 를 활용해서 명시적을 전달해 주기
>>> do_func(1,2,3,4,5,6,7,8,b=1000) 
1
(2, 3, 4, 5, 6, 7, 8)
1000

 

 

n개 이상(0개 포함)의 숫자를 아규먼트로 전달 받아 평균을 반환하는 함수를 만들어 주세요
단, 0개 아규먼트가 전달될 경우 None 반환!!!!

 

>>> def get_avg(*args):
>>>     result = None
>>>     if len(args) > 0:
>>>         result = sum(args) / len(args)
>>>     return result
    
# 파라미터 정의 * 의미는 패킹!!    
>>> def get_avg(*args): 
>>>     return  sum(args) / len(args) if len(args) > 0 else None

>>> print(get_avg(1,2,3,4,5,6))    
3.5

# 언패킹 get_avg(*tup) == get_avg(1,2,3,4,5,6,67)
>>> tup = (1,2,3,4,5,6,67)
>>> get_avg(*tup) 
>>> 12.571428571428571

>>> lst = [1,2,3,4,5,5]
>>> get_avg(*lst)
3.3333333333333335

>>> print(*lst)
1 2 3 4 5 5

 

packing , unpapacking

 

packing 하나의 변수에 여러 객체를 묶어서 담는 방식
unpacking 여러 객체를 묶고 있는 하나의 변수를 여러 변수에 풀어서 담는 방식

 

>>> lst1 = [1,2,3] # 패킹
>>> lst2 = [4,5,6] # 패킹
>>> for i1, i2 in zip(lst1,lst2): # 언패킹!!
>>>     print(i1,i2)    
1 4
2 5
3 6

>>> a,b = [1,2] # 언패킹
>>> print(a)
>>> print(b)
1
2

 

키워드 가변 파라미터

  •  함수를 정의하면서 keyword argument가 n개가 들어갈 수 있다(0개 포함)
  • 일반적으로 `**kwargs` 로 표현
  • 함수 내부에서 딕셔너리 형태로 묶인다
        - 변수명이 key, 값이 value가 된다

 

# ** 의미는 딕셔너리로 패킹한다는 의미
>>> def do_func(a,b,**kwargs): 
>>>     print(a)
>>>     print(b)
>>>     print(kwargs)

# c, karns, age는 파라미터로 정의 안되어 있으므로 kwargs 에 들어가게 됨
>>> do_func(10,b=20,c="hello",karns=100,age=43) 
10
20
{'c': 'hello', 'karns': 100, 'age': 43}

>>> kwargs_dict = {
>>>     "c" :  "hello",
>>>     "karns" : 100,
>>>     "age" : 43
>>> }

#언패킹
>>> do_func(10,b=20,**kwargs_dict)
10
20
{'c': 'hello', 'karns': 100, 'age': 43}

>>> kwargs_dict = {
>>>     "c" :  "hello",
>>>     "karns" : 100,
>>>     "age" : 43,
>>>     "a" : 10,
>>>     "b" : 20
>>> }

# 언패킹, do_func(c="hello",karns=100,age=43,a=10,b=20)
>>> do_func(**kwargs_dict) 
10
20
{'c': 'hello', 'karns': 100, 'age': 43}

 

람다 함수 (lambda)

  • 한줄짜리 간단한 함수를 만들 때 사용
  • 1회용 함수를 만들 때 많이 사용

 

>>> def add(num1,num2):
>>>     return num1+num2

>>> add(1,2)
3

>>> add_lambda = lambda num1,num2: num1+num2
>>> add_lambda(1,2)
3

>>> my_max = max
>>> my_max([1,2,3])
3
>>>

 

# 하나의 인수를 받아 제곱해서 반환하는 람다 함수를 만들어 보자
>>> square = lambda x: x**2
>>> square(5)

25

 

클로져 (Closure)

  • 함수 안에 함수를 정의 (내부함수)
  • 함수를 둘러싼 상태(지역변수, 파라미터)를 기억했다 함수를 실행할 때 다시 꺼내서 사용하는 기법
>>> def do_outer(a,b):
>>>     def do_inner(): # 내부함수
>>>         return a+b
>>>     return do_inner # 내부함수의 주소를 리턴!!

>>> inner_result1 = do_outer(10,20)
>>> inner_result2 = do_outer(30,50)
>>> print(inner_result1)
>>> print(inner_result2)
<function do_outer.<locals>.do_inner at 0x00000257070B5280>
<function do_outer.<locals>.do_inner at 0x00000257070B5430>

inner_result1()
30

inner_result2()
80

 

Callback Function

  • 콜백 또는 콜백함수라고 한다
  • 다른 코드의 인수로서 넘겨주는 실행코드
  • 함수의 인수로 사용되는 함수
# 어떠한 집계를 할 수 있는 함수와 리스트를 입력받아 집계하는 함수
>>> def aggregating_data(func,lst):
>>>     return func(lst)
    
>>> def avg(lst):
>>>     result = sum(lst) / len(lst)
>>>     return result    

>>> aggregating_data(avg,[30,40,50])
40.0

>>> aggregating_data(lambda lst:sum(lst) / len(lst) , [30,40,50] )
40.0

>>> aggregating_data(sum,[30,40,50])
120

 

>>> map_obj = map(lambda x: x**0.5, [2,3,4,5,6,7,8])
>>> type(map_obj)
>>> map

>>> list(map_obj)
[1.4142135623730951,
 1.7320508075688772,
 2.0,
 2.23606797749979,
 2.449489742783178,
 2.6457513110645907,
 2.8284271247461903]
 
>>> map_obj = map(lambda x1,x2: x1+x2 , [1,2,3] , [4,5,6])
>>> list(map_obj)
[5, 7, 9]

 

Decorator

  • 코드를 바꾸지 않고 공통기능을 추가하거나 수정하고 싶을 때 사용하는 기법

 

>>> def decorator_func(org_func): # 콜백함수를 받는다.
>>>     def wrapper_func(): # 콜백함수를 실행하는 내부 함수를 구현
>>>         print("오리지널 함수가 실행되기 전입니다.")
>>>         org_func()
>>>     return wrapper_func

>>> def do_func():
>>>     print("오리지널 함수가 실행되었습니다.")

>>> result = decorator_func(do_func)

>>> result()
오리지널 함수가 실행되기 전입니다.
오리지널 함수가 실행되었습니다.

>>> def decorator_func(org_func): # 콜백함수를 받는다.
>>>     def wrapper_func(): # 콜백함수를 실행하는 내부 함수를 구현
>>>         print("오리지널 함수가 실행되기 전입니다.")
>>>         org_func()
>>>     return wrapper_func

>>> @decorator_func
>>> def do_func():
>>>     print("오리지널 함수가 실행되었습니다.")

>>> do_func()
오리지널 함수가 실행되기 전입니다.
오리지널 함수가 실행되었습니다.

'파이썬 python' 카테고리의 다른 글

06 클래스  (0) 2023.05.11
05 예제  (0) 2023.05.09
04 예제  (2) 2023.05.07
04 제어문  (0) 2023.05.02
03 예제  (0) 2023.05.01