Networks/Python

SK networks AI Camp - Python(함수)

코딩하는 Español되기 2024. 7. 15. 08:00

함수(Function)

하나의 특별한 목적의 작업을 수행하기 위해 독립적으로 설계된 코드의 집합

1. 용어

  ○ 입력 변수(함수에 입력하는 변수) : 파라미터

  ○  출력 변수(함수 결과) : 리턴 값

 

2. 왜 사용해요?

  ○ 재사용성 : 반복적인 프로그래밍을 피하기 위해서

  ○ 코드의 가독성 : 모듈화로 인해 전체적인 코드의 가독성이 좋아짐

 

3. 함수 구조

# def 함수명(파라미터):
#	수행할 내용 1
#    수행할 내용 2
#    return 출력 변수

# 예시
def funcition(para):
    out = para * 5
    return out

4. 함수 생성

  ○ 입력변수 X, 출력변수 X

def func():			# 입력변수 X
    lst = [1, 2]
    for i in lst:
        print(i)
    # 출력변수 X

func()

  ○ 입력변수 O, 출력변수 X

break_num = 2
def func(p_break_num): # 입력변수
    lst = [1,2,3,4,5]
    for i in lst:
        print(i)
        if p_break_num < i:
            break
	# return 값 없음

func(break_num)

  ○ 입력변수 x, 출력변수 O

def add(): # 입력변수 X
    a, b = 3, 2
    return a + b # 출력변수 O
    
result = add()
result

  ○ 입력변수 O, 출력변수 X

a, b = 3, 5

def add(p_a, p_b):      # 입력변수 O
    return p_a + p_b    # 출력변수 O
    
result = add(a, b)
result


변수의 사용범위(Scope)

  ○ 지역변수(local) : 함수 내부에서 만들어진 변수, 함수 내에서만 사용가능(파라미터 포함)

  ○ 전역변수(global) : 함수 밖에서 만들어진 변수(어디서든 사용 가능)

  ○ 파이썬의 제어문은 해당 안됨! 제어문의 변수는 전역 변수

x = 10 # 전역 변수

def func():
    x = 20
    print(f'{x}는 지역변수이다.')

func()
print(f'{x}는 전역변수이다.')

함수 안에서 선언된 지역변수는 함수 밖에서는 사용할 수 없다.


함수 입력 변수

1. 디폴트 파라미터 : 입력변수값이 없는 경우에 기본값(디폴트)을 사용한다.

아래의 예제를 보면 함수를 호출하는데 입력 변수가 없어서 오류가 발생해요.

def add(a, b):
    return a + b
    
add() # 오류

만약 디폴트 파라미터를 적용하여 코드를 수정하면 입력 변수가 없지만 정상 실행되요.

def add(a=3, b= 3): # 디폴트 설정
    return a + b

add() 		# 파라미터가 없어도 기본값인 3,3 으로 6 출력
add(7, 8) 	# 파라미터를 설정하면 파라미터값인 7,8 으로 15 출력
add(b=7) 	# 파라미터 1개만 설정해주면 3, 7 으로 10 출력

디폴트 파라미터는 None을 사용할 수 있어요.

def add(a, b=None):
    if b is not None:
        return a + b
    else:
        return a + a

add(5, 7)

단, 디폴트 파라미터는 다른 파라미터보다 나중에 넣어줘야 해요.

def add(a = 3, b): # 오류
    return a + b
    
def add(a, b=3):	# 가능
	return a + b

 

2. 가변 파라미터

함수를 정의하면 Argument가 n개 이상 들어올 수 있다면 가변 파라미터를 정의해주면 되요(0개 포함)

* 을 사용하여 파라미터명을 정의. 일반적으로 *args로 표현

def add(*args):
    print(sum(args)) # sum()는 모든 변수들의 합을 리턴
    
add(1,2,3)
add(1,2,3,4,5,6,7,8,9,10)

def add(*args):
    print(sum(args)) # sum()는 모든 변수들의 합을 리턴
    
lst = [1,2,3,4,5]
add(*lst)

tup = (2,4,6,8)
add(*tup)

3. 키워드 가변 파라미터

  ○ 함수를 정의하면서 키워드 Argument가 n개 이상 들어올 수 있어요(0개 포함)

  ○ 일반적으로 **kwargs 로현해요

  ○ 함수내부에 딕셔너리 형태로 묶여요

  ○ 키워드 argument에서 키워드 = key 값, Argument = value 가 된다.

def user_info(**kwargs):
    print(kwargs)
    
user = { 
    'name' : '홍길동', 
    'age' : 44
}
user_info(**user)


람다 함수(lambda)

 ○ 한 줄 짜리 간단한 함수 만들 때 사용

 ○ 1회용 함수 만들 때 많이 사용

 ○ 아주 간단한 파라미터가 정의되거나 반환하는 함수일 경우 사용

# 기존 함수
def add(n1, n2):
    return n1 + n2

add(3,5)

# 람다 함수 사용
add_lambda = lambda n1, n2 : n1 + n2
add_lambda(3,5)
# 다른 예시
square_lambda = lambda x: x**2
square_lambda(3)

make_even = lambda x : [i for i in x if i % 2 == 0]
make_even([1,2,3,4,5,6,7,8])

클로져(Closure)

  ○ 함수 안에 함수(내부 함수 생성)

  ○ 함수를 둘러싼 지역변수(상태)를 기억하다가, 내부 함수 실행하면 기억한 지역변수 처리

def func_out(out_param):
    a = 10
    def func_in():
        return a + out_param
    return func_in

func = func_out(5)
func # 내부 함수인 func_in이 return 됨

def func_out(out_param):
    a = 10
    def func_in(in_param):
        return a + out_param + in_param
    return func_in

func = func_out(5)
func() # 내부함수의 in_param 값이 없어서 오류 발생


콜백함수(Callback Function)

  ○ 함수의 인자로 사용되는 함수

def call_func(a, func): # 콜백함수(func)를 변수로 받음
    return func(a)

def add_one(num):
    return num + 1

def add_three(num):
    return num + 3

call_func(3, add_one), call_func(3, add_three), call_func(2, lambda x : x*x)

def call_func(a, func1, func2): # 콜백함수(func)를 변수로 받음
    return func1(a) + func2(a)

def add_one(num):
    return num + 1

def add_three(num):
    return num + 3

call_func(3, add_one, add_three)

def add_one(num):
    return num + 1

def add_three(num):
    return num + 3

def call_func(a, *funcs): # 콜백함수(func)를 변수로 받음
    return funcs[0](a) + funcs[1](a)

lst_funcs = [add_one, add_three]
call_func(3, *lst_funcs)


Decorate

  ○ 코드를 변경하지 않고 기능을 추가 | 수정하고 싶을 때 정의하는 표현식

  ○ 내부함수의 주소를 리턴하는 클로져와 비슷, 함수를 다른 함수의 인자로 전달하는 방식과 비슷

  ○ 단순히 생각해서 두 가지 방식을 합친걸로 보면 편함

def decorator_func(org_func): # 함수를 인자로 받는다
    def wrapper_func(): # 내부함수를 구현
        print("org_func가 실행되기 전")
        org_func() # org_func 실행
    return wrapper_func # 내부함수의 주소 반환 

@decorator_func
def do_func():
    print('original 함수 실행')

do_func()

def decorator_func(org_func):
    def wrapper_func(*args,**kwargs):
        print(f"콜백함수가 실행되기 전입니다.")
        result = org_func(*args,**kwargs)
        print(f"콜백함수가 실행 완료 되었습니다.")
        return result
    return wrapper_func

# decorator_func(do_func)
@decorator_func
def do_func(a,b): # wrapper_func(*args,**kwargs)
    return a+b

do_func(3,5)


이터레이터(Iterateor)

for a in [1,2,3]:
	print(a)

위의 코드는 리스트 [1, 2, 3]을 for문으로 차레대로 하나씩 출력하는 예제입니다.

이렇게 for 문과 같은 반복 구문을 적용할 수 있는 리스트와 같은 객체를 반복 가능(Iterable)객체라고 해요

반복 가능한 개체 : 리스트, 튜플, 딕셔너리, 집합

lst 라는 리스트로 next() 함수를 호출했더니 리스트는 iterator 객체가 아니라는 오류가 발생했어요.

즉, 반복 가능하다고 iterator는 아니라는 거죠.

하지만 반복 가능하다면 아래 예제와 같이 iter() 함수를 이용해서 iterator로 만들 수 있어요.

lst = [1,2,3]
lst_iter = iter(lst)
type(lst_iter)

리스트를 이터레이터로 변경했으므로 next() 함수를 호출 가능해요.

next()를 호출 할 때 마다 이터레이터 객체의 요소를 차례대로 리턴하는 것을 확인 가능해요.

하지만 더 이상 리턴할 값이 없으면 위와 같이 StopIteration 예외가 발생해요.

이터레이터의 값을 가져오는 가장 일반적인 방법은 for 문을 이용하는 것이 있어요.

a = [1,2,3]
lst_iter = iter(a)
for i in lst_iter:
    print(i)
    
for i in lst_iter:
    print(i)


제너레이터(Generator)

  ○ 이터레이터를 생성해주는 함수

  ○ 제너레이터로 생성한 객체는 이터레이터와 마찬가지로 next() 함수 호출 시 그 값을 차례대로 얻을 수 있어요.

  ○ 제너레이터에서는 차례대로 결과를 반환하고자 yield 키워드를 사용해요.

def gener():
    for i in [1,2]:
        yield i
        
g = gener()
type(g)

next(g)
next(g)
next(g)

 

이렇게 오늘은 함수에 관해서 알아보았어요. 내장 함수 부분은 따로 포스팅 할게요.