태코놀로지

함수와 제너레이터 (Functions and Generators) 본문

Python3/EECS-WinterSchool

함수와 제너레이터 (Functions and Generators)

태코놀로지 2017. 1. 28. 22:06

2.5 Functions and Generators

파이썬은 다른 언어에 비해 인자(argument) 처리에 있어서 유연한데, 파이썬에서 자주 사용하는 위치 인자 및 키워드 인자에 대해서 알아본다. 인자의 가장 익숙한 형태는 값을 순서대로 상응하는 매개변수에 복사하는 위치 인자(positional arguments)다. 이는 매우 일반적이지만 각 위치의 의미를 사전에 알고 있어야한다는 단점이 있다. 위의 위치 인자가 가지는 문제점을 보완하기 위해서 제공하는 것이 바로 키워드 인자(keyword arguments)다. 키워드 인자는 순서에 상관없이 인자를 매개변수에 복사할 수 있다.


위치 인자와 키워드 인자로 함수를 호출한다면 위치 인자가 먼저 와야 한다. 그러나 보다 파이써닉한 방법에서는 위치 인자와 키워드 인자를 섞어쓰지 않는 것을 권장한다. 이런 방법은 코드를 읽는 사람으로 하여금 가독성과 코드이해도를 저해시킬 수 있다. 아래의 예제들을 통해서 함수를 정의하고, 호출할 때 위치 인자 및 키워드 인자의 사용법에 대해서 알아보자.



키워드 인자를 포함하여 함수를 정의할 때에는 기본값을 정의할 수 있다. 따라서 함수를 호출할 때에 정의된 파라미터를 모두 전달할 필요 없이 위치 인자에 해당하는 파라미터 전달만 필요하다. 키워드 인자에 해당하는  파라미터가 전달되지 않을 경우, 함수를 정의할 때 작성했던 기본값으로 대체되어 적용된다.



파라미터로 전달된 위치 인자와 키워드 인자의 종류 및 수를 확인하기 위해서 위치 인자 모으기 및 키워드 인자 모으기를 구현해본다. 이를 위해서는 애스터리스크(*) 문자를 사용하는데, 애스터리스크를 통해서 매개변수에서 위치 인자 변수들을 튜플로 묶을 수 있다. 특히 가변 인자를 사용하는 print( )와 같은 함수에서 입력되는 인자를 모으는 것은 매우 유용하게 사용될 수 있다. 함수 print_more( )와 같이 함수의 위치 인자를 지정할 때, 맨 끝에 *args를 사용하여 나머지 인자를 모두 취하게 할 수 있다. 아래의 예시에서 print_args( ) 함수에 인자를 전달하여, args 매개변수 튜플의 출력 결과를 살펴보자.



키워드 인자를 딕셔너리로 묶기 위해 두 개의 애스터리스크(**)를 사용할 수 있다. 인자의 이름은 키고, 값은 이 키에 대응하는 딕셔너리 값이다. 위치 매개변수와 *args, **kwargs를 섞어서 사용하려면 이들을 순서대로 배치해야 한다. 그리고 args와 마찬가지로 키워드 매개변수의 이름은 kwargs로 할 필요는 없지만 관용적으로 kwargs를 사용한다.



가독성은 중요하다라는 구절이 파이썬의 철학에 포함된다. 그렇다면 어떻게 함수에 대한 가독성을 향상시킬 수 있을까? 함수 몸체 시작 부분에 함수에 대한 간략한 설명을 덧붙이는 문자열을 포함시킬 수 있다. 이것이 바로 함수의 docstring이라고 부른다. help 함수를 통해서, 함수에 작성된 docstring을 확인할 수 있다.



제너레이터(generator)는 파이썬의 시퀀스를 생성하는 객체다. 제너레이터를 활용하여 전체 시퀀스를 한 번에 메모리에 생성하고 정렬할 필요 없이, 잠재적으로 매우 큰 시퀀스를 순회할 수 있다. 제너레이터는 이터레이터에 대한 데이터의 소스로 자주 사용된다. 대표적인 제너레이터인 range를 통해 일련의 정수를 생성할 수 있다.


제너레이터를 순회할 때마다 마지막으로 호출된 항목을 기억하고 다음 값을 반환한다. 제너레이터의 이런 특성은 일반 함수와는 구별되는 다른 특징이다.. 일반 함수는 이전 호출에 대한 메모리가 없고, 항상  똑같은 상태로 첫 번째 라인부터 동작한다. 이에 반해 제너레이터는 호출된 정보를 기억하고 있는다. 따라서 잠재적으로 매우 큰 시퀀스를 생성하고, 제너레이터 컴프리헨션에 대한 코드가 아주 긴 경우에는 제너레이터 함수를 사용하면 된다. 제너레이터 함수는 일반 함수와 유사하지만 return 문이 아닌, yield 문으로 값을 반환하는 차이가 있다.




Comments