상세 컨텐츠

본문 제목

5. 함수

Python

by evaseo 2021. 4. 25. 16:04

본문

 

함수: 여러 개의 명령문을 하나의 묶음으로 만든 실행단위

1.     함수를 사용하는 이유

(1)     반복되는 부분이 있을 때 정의

(2)     프로그램 흐름을 일목요연하게 보여줄 수 있다.

 

2.    사용자 정의 함수

(1)     형식
def
함수이름(매개변수):
   
수행할 문장….

 

(2)     매개변수와 인수

1)       매개변수(parameter): 함수에 입력으로 전달된 값을 받는 변수 => a, b

2)       인수(argument): 함수를 호출 할 때 전달하는 입력 값 => 3, 4
ex) def add(a, b):
       return a+b
   print(add(3, 4))

 

(3)     입력 값과 결과값에 따른 함수 형태 4가지

1)       일반적인 함수

        입력 값과 결과값이 있는 함수

        형식:
def
함수이름(매개변수):
   
수행할 문장….
return
결과값

2)       입력 값이 없는 함수

3)       결과값이 없는 함수: return이 없는 함수. 수행할 문장만 존재
ex) def add(a, b):
       print(“%d, %d
의 합은 %d입니다.”%(a, b, a+b)) => 수행할 문장

 

(4)     입력 값과 결과값이 없는 함수
ex) def say():
       print(“hi”)
호출: say() => hi

 

(5)     매개변수 지정, 미 지정

1)       지정

        함수 호출할 때변수 명 = 으로 명시

        매개변수와 인수의 개수를 맞춰줘야 함. type은 명시하지 않으므로 안 맞춰도 됨

2)       미 지정: 여러 개의 매개변수를 받는 것 가능

형식
def
함수이름( * 매개변수, ** 매개변수):
   
수행할 문장….

        매개변수 앞에 *을 붙이면 입력 값을 모두 모아 튜플로 만들어준다.

        매개변수 앞에 **을 붙이면 딕셔너리로 만든다.

ex)

def func4(a,b,*v1,**v2):
    print(a,b)
    print(v1)
    print(v2)

func4(1,2)
func4(1,2,3,4,5)
func4(1,2,3,4,5,kbs=9,sbs=5)   ​
실행결과

*은 함수에 사용하지 않을 때는 값을 할당하는 용도로 사용한다.
ex)
*v1, v2, v3 = [1, 2, 3, 4, 5]

print(v1,v2,v3)
       => [1, 2, 3] 4 5

 

(6)     매개변수 초기 값 미리 설정

1)       항상 변하는 값이 아닌 매개변수를 설정할 때는 초기값을 설정가능

2)       초기값이 설정된 매개변수는 무조건 맨 뒤에 입력

3)       초기값을 설정해 놓은 매개변수는 따로 인수를 주지 않으면 초기 설정한 값을 반환한다.

ex) def say_myself(name, old, man=True):
       print(“
나의 이름은 %s입니다.”%name)
       print(“
나이는 %d살 입니다.”%old)
       if man:
           print(“
남자입니다.”)
       else:
           print(“
여자입니다.”)
호출: say_myself(“tom”, 27) =>
나의 이름은 tom입니다.
나이는 27살 입니다,
남자입니다.

 

(7)     함수의 결과값은 한 개

1)       return a, b: 튜플로 만들어서 반환 (a, b)

2)       return1, return2로 결과값 설정: 값이 2개 반환

3)       return a, return b: a만 반환, b는 실행 안됨

 

함수는 return을 만나면 함수를 빠져나감

=> 함수를 강제종료 하고싶을 때 return 설정 가능

 

(8)     함수실행

1)       함수를 실행할 때는 함수 명 뒤에 ([매개변수])를 붙여줘야 한다.

2)       함수 명만 명시할 때는 함수가 저장된 메모리의 주소가 참조됨

 

(9)     변수

1)       전역(Global)변수: 모듈 수준에서 정의된 변수

2)       지역(Local)변수: 함수 내에서 정의된 변수

3)       변수 영역(Scope)의 접근 순서: Local → Enclosing Function → Global

a=10; b=20; c=40 #전역변수, 자바의 public정도로 생각해도됨. 다른 모듈에서도 사용가능
print('1) a:{}, b:{}, c:{}'.format(a, b, c))

def Foo():
    a=40 #Foo함수 내의 지역변수, 영역밖에서는 쓸 수 없는 지역변수
    b=50 #영역밖에서는 쓸 수 없는 지역변수
    def Bar(): #함수내에서 함수를 선언하고
        #UnboundLocalError c 해결법 1)
        #c=60 #영역밖에서는 쓸 수 없는 지역변수
        
        #UnboundLocalError c 해결법 2) c를 전역변수로 선언
        global c
        
        #UnboundLocalError b 해결법) 전역변수가 아니라 Foo내의 b=50의 수준과 같게 맞춤
        nonlocal b # Bar의 지역변수를 Enclosing function의 변수로 취급한다는 뜻
        
        print('Bar()> a : {}, b : {}, c : {}'.format(a, b, c))
        
        c=60 #UnboundLocalError: local variable 'c' referenced before assignment. 실행오류: c를 치환하기 전에 참조해서 에러남
        b=70 #UnboundLocalError: local variable 'b' referenced before assignment
        
    Bar() #호출도 함수 내에서 해줘야함. 밖에서 하는것이 아니라    
    print('Foo()> a : {}, b : {}, c : {}'.format(a, b, c))

#변수찾는 순서: 먼저 Bar()를 정의한 내에서 a,b,c 찾고 없으면 Foo()내에서 찾고 a,b는 있으니깐 가져다 쓰고 c는 없으면 전역변수로 찾기.
Foo()
print('3) a:{}, b:{}, c:{}'.format(a, b, c))
        
        c=60 #UnboundLocalError: local variable 'c' referenced before assignment. 실행오류: c를 치환하기 전에 참조해서 에러남
        b=70 #UnboundLocalError: local variable 'b' referenced before assignment
        
    Bar() #호출도 함수 내에서 해줘야함. 밖에서 하는것이 아니라    
    print('Foo()> a : {}, b : {}, c : {}'.format(a, b, c))

#변수찾는 순서: 먼저 Bar()를 정의한 내에서 a,b,c 찾고 없으면 Foo()내에서 찾고 a,b는 있으니깐 가져다 쓰고 c는 없으면 전역변수로 찾기.
Foo()
print('3) a:{}, b:{}, c:{}'.format(a, b, c))​
실행결과

 

(10)   클로저함수(closure)

1)       내부함수의 주소를 반환해서 함수의 멤버를 계속적으로 참조. 변수영역(Scope)에 제약을 주지 않는 함수

2)       실행을 반환하는 것이 아니라 내부함수의 주소를 반환. 반드시 함수 return()를 붙이지 않고 함수명만 return해야함

3)       함수의 주소를 참조하기 때문에 함수밖에서 함수 내부의 변수를 유지시키는 것. 초기화를 만나지 않고 누적됨.

4)       자신의 영역 밖에서 호출된 함수의 변수 값과 레퍼런스를 복사, 저장, 접근을 가능하게 하는 것

ex1)

def outer():
    count = 0
    def inner():
        nonlocal count 
        count +=1
        return count
    return inner #closure 내부함수의 주소를 반환. 실행을 반환하는 것이 아니라

obj1 = outer() #obj1는 outer()를 실행해서 inner의 주소를 갖는다.
print(obj1())
result = obj1()
print(result)
print(obj1())
#함수밖에서 함수 내부의 변수를 유지시키는 것. 초기화를 만나지 않고 누적됨. inner함수의 주소를 받기 때문에
#inner에서 count = 0을 선언했다면 계속 초기화 되었을 것.​
실행결과

ex2)

print('\n수량*단가*세금 결과 출력-------------------------')
def outer2(tax):
    def inner2(su, dan):
        amount = su * dan * tax
        return amount
    return inner2 #closure - 주소반환
q1 = outer2(0.1)
result1 = q1(5, 10000)
print('result1:',result1)

#0.1의 tax값을 계속 사용
result2 = q1(10, 20000)
print('result2:',result2)

q2 = outer2(0.05)
result3 = q2(5, 10000)
print('result3:',result3)

result4 = q2(10, 20000)
print('result4:',result4)

#q1로 계속 작업하면 tax를 0.1로 계산되고, q2로 작업하면 tax를 0.05로 계속 계산 된다.
실행결과

 

(11)   재귀함수(recursion) 함수

1)       스스로가 자기자신을 부르는 것

2)       반복 처리할 때 사용

ex)

print('\n재귀함수(recursion 함수 스스로가 자기자신을 부르는것, 반복처리할 때 사용)-------------------------')

def CountDown(n):
    if n==0:
        print('처리완료')
    else:
        print(n, end=' ')
        CountDown(n-1) #함수가 자기를 호출

CountDown(5)

def totFunc(su):
    if su ==1:
        print('처리 끝')
        return True
    return su + totFunc(su-1)

print('10까지의 합은? ',totFunc(10))

#5!만들어보기

def fac(su):
    if su ==1:
        print('처리 끝')
        return True
    return su * fac(su-1)
print(fac(5))​
실행결과

 

(12)   일급함수

1)       인자로 함수사용

2)       함수 안에 함수 선언가능

3)       반환 값으로 함수가능

#일급함수: 함수 안에 함수 선언가능, 인자로 함수사용, 반환값이 함수가능

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

# 주소를 기억하는 방법 1)assignment
func2 = func1 #함수의 주소를 치환
print('func1(2,3):', func1(2,3))
print('func2(2,3):', func2(2,3))
 
# 주소를 기억하는 방법 2)argument
def func3(func): # 1. 인자로 함수 사용
    
    def func4(): # 2. 함수안에 함수 선언
        print('func4() 나는 내부 함수')
    func4()
    return func # 3. 반환값이 함수

#mbc는 func1의 주소를 가지고 있는 것
mbc = func3(func1) 
print('mbc(3,4):', mbc(3,4)) 
# func4가 먼저 수행되고 다음에 argument인 함수가 실행됨 => 나는내부함수 다음에 7이 나오는 것
실행결과

     함수의 주소를 기업하는 방법 2가지

n  assignment: 함수의 주소를 치환(변수에 ()를 안 붙인 함수명을 =이용해 표현)

n  argument: 인자로 함수사용

 

(13)   람다함수(lambda)

1)       보통함수를 한 줄로 간결하게 만들 때 사용

2)       형식
lambda
매개변수:함수… : 매개변수를 사용한 표현식

3)       이름이 없는 한 줄 함수 표현
ex)

#람다함수: 이름이 없는 한줄짜리 함수 - 복잡하지 않는 함수를 대체할 수도 있다.
print('\n\nlambda: 이름이 없는 한 줄 짜리 함수--------------------')
#형식: Lambda arg....: 표현식 <== return문 없이 결과 반환

def hap(x,y):
    return x+y

print('일반적인 함수 정의:',hap(2, 4))

#hap함수를 lambda로 표현
aa = lambda x, y:x+y #aa는 lambda에 대한 실행 주소를 가진다.
print('lambda:',aa(2,4))

kbs = lambda a, su=10:a+su
print(kbs(5))
print(kbs(5, 6))

sbs = lambda a, *tu,**di : print(a,tu,di)
sbs(1,2,3,tvn=3,ytn=24)

li=[lambda a,b :a+b, lambda a,b :a*b]
print(li[0](3,4))
print(li[1](3,4))​
실행결과

4)       다른 함수에서 인자 값으로 함수 표현

        형식:
filter(
함수, 집합형 자료)
ex)

print('다른 함수에서 인자값으로 lambda를 사용 가능----------')
# 형식: filter(함수, 집합형 자료)

print(list(filter(lambda a:a<5,range(10)))) 
#함수: lambda a:a<5, 집합형 자료: range(10)

print(tuple(filter(lambda a:a%2,range(10)))) 
#0아닌 숫자는 true라서 나머지가 1인 홀수들만 찍히게 됨.​
실행결과

 

(14)   함수장식자

1)       meta 기능이 있다.

2)       형식: @함수명

ex)

print('함수 장식자(decorater)--------------------------')
#함수 장식자: meta 기능이 있다. 
# 형식: @함수명
def make2(fn):
    return lambda :'안녕'+fn() #인자가 없는 함수를 리턴

def make1(fn):
    return lambda :'반가워'+fn()

def hello():
    return "신기해"

hi = make2(make1(hello)) 
#hello()=신기해 아님. 함수를 가져가야 리턴되니깐 , hi는 lambda :'안녕'+fn()의 주소를 받음
print('hi():', hi())

@make2
@make1
def hello2():
    return "신기루"

print('hello2()', hello2()) # hi와 같은 형태

hi2 = hello2()
print('hi2:', hi2)

hi3 = hello2
print('hi3:', hi3)
print('hi3():', hi3())
실행결과

'Python' 카테고리의 다른 글

7-1. 클래스  (0) 2021.04.25
6. 모듈(module)  (0) 2021.04.25
4. 제어문 - if, while, for  (0) 2021.04.25
3. 파이썬 자료형 - (3) list, tuple, Dictionary, set, boolean, 변수  (0) 2021.04.25
3. 파이썬 자료형 - (2) 문자열  (0) 2021.03.04

관련글 더보기