티스토리 뷰

Python

[Python] 함수 (Function)

ellie.strong 2021. 7. 16. 15:49
728x90

<목차>

     

    파이썬에서의 함수에 대해서 자세히 알아보자!!

     

    <Function vs Method>

     

    <일급 객체(First-class Object)>

    파이썬에서 함수는 일급 객체(First-class Object)로 불린다. 

    C언어에서는 포인터가 일급 객체로 불린다. 

     

    <함수를 식별자로 쓸 수 있다.>

    함수의 인자로 함수를 넣을 수 있다. 

    def answer():
    	print(42)
    
    def run_something(func):
    	func()
    
    run_something(answer) # answer 함수 객체를 넘긴다.
    
    run_something(answer()) # answer 함수의 반환값을 넘긴다. (None)

     

    함수의 인자로 함수, 그 함수의 인자까지 넣을 수 있다. 

    def add_args(arg1, arg2):
    	print(arg1 + arg2)
    
    def run_something_with_args(func, arg1, arg2):
    	func(arg1, arg2)
        
    def run_something_with_args(add_args, 5, 9)

     

    함수의 인자로 가변 인자를 넣을 수 있다. 

    def sum_args(*args):
    	return sum(args)
    
    def run_with_positional_args(func, *args):
    	return func(*args)
    
    run_with_positional_args(sum_args, 1, 2, 3, 4)

     

    <독스트링(docstring)>

    파이썬에서는 가독성을 매우 중요시 여긴다. 

     

    함수 바디 시작 부분에 문자열을 포함시켜 함수 정의에 문서를 붙일 수 있다. 

     

    <메인함수>

     

    if __name__ == "__main__":
    	main()

     

    모듈(module)에서 가장 먼저 찾고자 하는 함수 = __main__

     

    클래스(class)서 가장 먼저 찾고자 하는 함수 = __init__

     

     

    <내부 함수 / 익명 함수>

    몰라도 코드 작성 시 문제되는 부분은 없다. 하지만 알아두면 코드를 효율적으로 작성할 수 있다. 

     

    내부(inner) 함수

    외부 함수의 인수 및 변수를 사용할 수 있다. 

    반복문이나 코드 중복을 피하고자 사용한다. 

    def knights2(saying):
    	def inner2():
        	return "We are the knights who say : '%S'" % saying
        return inner2

     

    파이썬 = 절차형 언어, 선언형 언어
    R = 함수형 언어

    Programming paradigm - Wikipedia

     

    Programming paradigm - Wikipedia

    From Wikipedia, the free encyclopedia Jump to navigation Jump to search A programming paradigm defines the methodology of designing and implementing programs using key features and building blocks of a programming language . This article is about classific

    en.wikipedia.org

     

    클로저(closure)

    내부 함수가 정의된 스코프에서 외부 함수의 변수를 활용할 수 있다. 

    함수형 언어에서 나온 기능이다. 

    - nonlocal

     

    익명 함수(anonymous function, lambda function, lamda expression)

    프로그램 내부 루틴의 공간적 요소를 효율적으로 개선 가능하다. 

     

     

    <제너레이터(Generator)>

    제너레이터는 시퀀스를 생성하는 객체이다. 

    함수도 객체다!! 제너레이터도 객체다!!

     

    전체 시퀀스를 한번에 메모리에 생성하고 정렬할 필요 없이, 잠재적으로 아주 큰 시퀀스를 순회할 수 있다. 

    - 전체를 몰라도 next()를 타고가면서 순회할 수 있다. 

     

    return 문으로 값을 반환하지 않고 yield 문으로 값을 반환한다. 

    - return : 코드 실행의 제어 루틴이 바로 전환된다. 

    - yield : 비동기 처럼 동작한다. 추가 작업을 할 수 있다. 

     

    def my_range(first=0, last=10, step=1):
    	number = first
    	while number < last:
    		yield number
    		number += step

     

    type(my_range)
    
    Out[3]: function

     

    ranger = my_range(1, 5)
    
    type(ranger)
    
    Out[7]: generator
    
    ranger
    
    Out[9]: <generator object my_range at 0x00000144374B0C80>

     

    ranger 제너레이터의 경우 한번만 사용 가능하다. 한번 순회를 돌고 나면 끝!!

    - 다시 사용하고 싶으면 my_range(1, 5)로 다시 만들어 주어야한다. 

    for x in ranger:
        print(x)
        
    1
    2
    3
    4

     

    제너레이터 컴프리헨션

    genobj = (pair for pair in zip(['a','b'], ['1', '2']))
    
    genobj
    
    Out[12]: <generator object <genexpr> at 0x00000144374F4200>

     

    for thing in genobj:
    	print(thing)
        
    ('a', '1')
    ('b', '2')

     

    <데코레이터(decorator)>

    하나의 함수를 취해서 또 다른 함수를 반환한다. 

     

    - 사용하고 있는 함수를 코드의 수정 없이 변경 가능하게 한다. 

    - 기존 프로그래밍 언어의 override와 비슷해보이지만 다르게 동작한다. 

     

    add_inits 함수를 변경해보자!!

    def add_ints(a, b):
    	return a + b
        
    add_ints(3, 5)
    
    Out[17]: 8

     

    ① 데코레이터 생성

    def document_it(func):
    	def new_function(*args, **kwargs):
    		print(f'Running function: {func.__name__}')
    		print(f'Positional arguments: {args}')
    		print(f'Keyword arguments: {kwargs}')
    		result = func(*args, **kwargs)
    		print(f'Result: {result}')
    		return result
    	return new_function

     

    ② 데코레이터 수동 할당 및 실행

    cooler_add_ints = document_it(add_ints)
    
    cooler_add_ints(3, 5)
    
    Running function: add_ints
    Positional arguments: (3, 5)
    Keyword arguments: {}
    Result: 8
    Out[19]: 8

     

    ③ 어노테이션을 붙여서 데코레이터를 자동 할당할 수 있다. 

    @document_it
    def add_ints(a, b):
    	return a + b
        
    add_ints(3,5)
    
    Running function: add_ints
    Positional arguments: (3, 5)
    Keyword arguments: {}
    Result: 8
    Out[21]: 8

     

    ④ 두개의 데코레이터를 동시에 할당할 수 있다. 

    - def와 가까운 순으로 데코레이터가 실행된다. 

    def square_it(func):
        def new_function(*args, **kwargs):
            result = func(*args, **kwargs)
            return result * result
        return new_function
        
    @document_it
    @square_it
    def add_inits(a, b):
        return a + b
        
    add_inits(3, 5)
    
    Running function: new_function
    Positional arguments: (3, 5)
    Keyword arguments: {}
    Result: 64
    Out[24]: 64

     

    - 두 데코레이터의 순서를 바꿀 경우 결과 값은 64로 같지만 그 중간 과정이 바뀐다. 

    @square_it
    @document_it
    def add_inits(a, b):
        return a + b
        
    add_inits(3, 5)
    
    Running function: add_inits
    Positional arguments: (3, 5)
    Keyword arguments: {}
    Result: 8
    Out[26]: 64

     

     

    <네임스페이스 / 스코프>

    네임스페이스

     

    스코프

    클로저를 이해할 경우 4계층으로도 나눠서 생각할 수 있다. 

    - enclosing scopes

     

    <재귀함수>

    대상 함수가 자기 자신을 다시 호출하는 함수이다. 

     

    - 함수 종료 구간을 반드시 명시해야한다.

    - 문제를 분해할 수 있도록 작성해야한다. 

     

    def factorial(n):
        if n == 1:  # n이 1일 때
            return 1  # 1을 반환하고 재귀호출을 끝냄
        return n * factorial(n - 1)  # n과 factorial 함수에 n - 1을 넣어서 반환된 값을 곱함
        
    print(factorial(5))
    
    120

     

    def hello():
        print('Hello, world!')
        hello()
        
    hello()
    
    # 종료구간을 설정해주지 않으면 재귀함수가 계속 돌다가 에러를 방생 시킴
    RecursionError: maximum recursion depth exceeded while calling a Python object

     

    sys 라이브러리를 이용하여 재귀함수의 제한을 확인할 수 있으며 설정할 수도 있다. 

    import sys
    
    sys.getrecursionlimit() # get limit
    
    Out[32]: 3000
    
    sys.setrecursionlimit(1500) # set limit

     

    flatten() 함수

    "리스트의 리스트"와 같은 복잡한 데이터를 모두 같은 레벨의 리스트로 "평평하게" 만들어준다. 

    def flatten(lol):
        for item in lol:
            if isinstance(item, list):
                for subitem in flatten(item):
                    yield subitem
            else:
                yield item
                
    lol = [1, 2, [3, [4, 5, [6, 7, 8], 9, 10], [11, 12], [13, [14, 15], 16], 17], 18, [19, 20]]
    
    flatten(lol)
    
    Out[40]: <generator object flatten at 0x00000144374B0C10>
    
    list(flatten(lol)) # generator의 값을 확인하고 싶을 경우 list로 바꿔서 사용
    
    Out[41]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

     

    <예외(syntax errors / exceptions)>

    일부 언어에서 에러는 특수 함수의 반환값으로 다룬다. 

     

    파이썬에서는 예외가 발생할 경우 실행되지 않는다. 

    short_list = [1, 2, 3]
    position = 5
    short_list[position]
    
    IndexError: list index out of range

     

    ① 에러 처리하기 : try, except

    - 두 개 이상의 예외 타입이 발생하면 별도의 예외 핸들러(exept)를 제공하는 것이 가장 좋은 방법이다. 

     

    except [에외 타입] as [이름] 으로 예외 객체를 확인할 수도 있다. 

    short_list = [1, 2, 3]
    
    while True:
    	value = input("Position [q to quit]?")
    	if value == 'q':
    		break
    	try:
    		position = int(value)
    		print(short_list[position])
    	except IndexError as err:
    		print(f"Bad index: {position}")
    	except Exception as other:
    		print(f"Something else broke: {other}")
            
    Position [q to quit]?>? 1
    2
    Position [q to quit]?>? 2
    3
    Position [q to quit]?>? 3
    Bad index: 3
    Position [q to quit]?>? 4
    Bad index: 4
    Position [q to quit]?>? d
    Something else broke: invalid literal for int() with base 10: 'd'
    Position [q to quit]?>? q

     

    ② 예외 만들기 : raise

    문자열에 대분자가 있을 때 예외를 발생시키는 UppercaseException 예외를 만들 수 있다. 

    - 예외는 Exceptions 클래스를 상속받는 클래스이다. 

    class UppercaseException(Exception):
    	pass
        
    words = ['eenie', 'meenie', 'miny', 'MO']
    
    for word in words:
    	if word.isupper():
    		raise UppercaseException(word)
        
    UppercaseException: MO # 우리가 생성한 예외가 발생한다.

     

    ③ 예외 처리를 마치고 나면 : finally

     

     

     

     


    ref.

    - 2021 청년취업 아카데미 파이썬 수업

    - 처음 시작하는 파이썬, 빌 누바노빅

     

    728x90
    댓글
    공지사항
    최근에 올라온 글