파이썬 강좌 – 다양한 함수 인수 ~ 유연한 함수 만들기

  1. 프롤로그
  2. 개발 첫걸음
    1. 컴퓨터 구성요소 – 컴퓨터는 어떤 걸 할 수 있나?
    2. 개발과 관련된 용어
    3. 파이썬의 선택 – 왜 파이썬인가?
    4. 파이썬 설치 – Hello World 출력하기
    5. Visual Studio Code 의 편리한 기능
    6. REPL과 콘솔 창 – 파이썬 동작시키기
  3. 파이썬 기초
    1. 기초 입출력 – 소통하기
    2. 변수와 대입 – 기억하기
    3. 연산자 – 계산하기
    4. 조건문 – 분기를 만들기
    5. 반복문 – 비슷한 작업을 반복하기
    6. 반복문 코딩하기
    7. 변수와 리스트 – 비슷한 변수들을 묶기
    8. for, range – 리스트의 항목을 다루기
    9. 함수와 메소드의 호출 – 편리한 기능 이용하기
    10. 모듈 설치와 사용 – 유용한 기능 끌어다 쓰기
    11. 문자열 – 텍스트 다루기
  4. 파이썬 중급
    1. 함수를 직접 만들기 – 자주 쓰는 기능을 묶기
    2. 딕셔너리, 튜플, 세트 – 변수를 다양한 방법으로 묶기
    3. 클래스와 객체 – 변수를 사람으로 진화시키기
    1. 상속 – 클래스를 확장하기
    2. 정체성과 동질성 – 객체의 성질
    3. 특별 메소드와 연산자 – 파이썬의 내부 작동방식 이해하기
    4. 다양한 함수 인수 – 유연한 함수 만들기
    5. 슬라이싱 – 리스트 간편하게 접근하기
    6. 지능형 리스트(List Comprehension) – 리스트 갖고 놀기
    7. namedtuple - 데이터 묶음 손쉽게 만들기
    8. 조건 표현식 (Conditional Expression) - 간단한 분기 나타내기
    9. 코드 스타일 - 코드의 일관성 유지하기
    10. 명령문, 표현식 – 문법을 이루는 것들
    11. 본격적인 검색 해보기
  5. 파이썬 고급
    1. 일급 함수 다루기
    2. NotImplementedError와 NotImplemented
    3. 어노테이션 – 수월하게 프로그래밍하기
    1. 내장 함수 톺아보기
    2. 예외와 에러 – 예상치 못한 상황에 대응하기 (v0.1)
    3. 변수의 범위 – 이름 검색의 범위
  6. 파이썬 심화
    1. 시퀀스와 반복자 – 반복과 순회를 자유자재로 다루기
    2. 데코레이터 – 함수의 기능을 강화하기
    3. 프로퍼티
    4. 제너레이터
    5. async와 await
    6. 객체로서의 클래스 – 클래스를 동적으로 정의하기
  7. 파이썬 프로젝트 실습
    1. 원카드 게임 만들기 (1)
    2. 원카드 게임 만들기 (2)
    3. 원카드 게임 만들기 (3) (작성중)
    4. 턴제 자동 전투 게임 만들기 (작성중)
  8. 실전 (파이썬 외적인 것들)
    1. 정규표현식 – 문자열을 검색하고 치환하기 (작성중)
    2. 유니코드 – 컴퓨터에서 문자를 표기하는 방법
    3. html, css, 인터넷 – 자동화 첫 걸음 내딛기
    4. 네트워크 – 인터넷으로 통신하는 방법
    5. 문서 – 문맥을 읽어보기

기본값(default) 지정

파이썬에서는 함수를 호출할 때 인수가 적절하게 들어가있어야 합니다. 하지만 기본값이 정해진 인수는 함수 호출 시 생략하여도 무방합니다. 기본값을 설정하는 방법은 함수 정의 시 변수명=값 으로 작성하는 것입니다. (함수 호출시 등호(=)를 이용하는 건 또 다른 개념입니다.) 다음 예제를 참고해주세요.

def say_hi(a='철수', b=10, c=20):
    print('안녕 ' + str(a) + '야, ' + '나는 ' + str(b) + 
        '살이고 내 형은 ' + str(c) + '살이야.')

say_hi()
say_hi('영미')
say_hi('영미', 15)
say_hi('영미', 15, 25)

다음은 결과입니다.

안녕 철수야, 나는 10살이고 내 형은 20살이야.
안녕 영미야, 나는 10살이고 내 형은 20살이야.
안녕 영미야, 나는 15살이고 내 형은 20살이야.
안녕 영미야, 나는 15살이고 내 형은 25살이야.

기본값을 넣은 인수 이후에는 기본값이 없는 인수가 등장할 수 없습니다. 아래와 같은 코드를 사용하게 되면 함수 정의 단계에서 에러가 발생합니다.

def say_hi(a='철수', b, c=20):
    print('안녕 ' + str(a) + '야, ' + '나는 ' + str(b) + 
        '살이고 내 형은 ' + str(c) + '살이야.')
  File "c:/Users/tooth/Desktop/test.py", line 1
    def say_hi(a='철수', b, c=20):
              ^
SyntaxError: non-default argument follows default argument

b는 기본값이 없으므로 무조건 채워야 하는데, b의 위치는 두번째입니다. 즉 b의 내용을 채워넣으려면 첫번째인 a 또한 매번 인수로 값을 받을 수 밖에 상황이기에 adefault는 사실상 필요가 없어집니다. 이러한 설계상의 결함을 최소화하기 위해 아예 에러로 처리하는 파이썬 인터프리터의 모습을 확인할 수 있습니다. (추가 예정)


가변 인수 (variadic arguments)

파이썬은 가변 인수를 활용할 수 있습니다. 가변 인수란 "인수의 개수가 변할 수 있다"라는 뜻입니다. 특징은 다음과 같습니다.

  • 변수명 바로 앞에 별표(*)만 첨가하여 바로 사용할 수 있습니다.
  • 함수 내에서 튜플(tuple) 로 제공됩니다.
  • 기본값을 지정할 수 없습니다.
  • 함수에 하나에 최대 하나만 존재합니다. def example(a, *b, *c):와 괕이 정의하면 바로 에러가 발생합니다.
  • 함수를 호출할 때 가변 인수에 값이 하나도 전달되지 않아도 됩니다.
def example(apple, banana, *stuff):
    print(apple, banana, stuff)
example('철수', '영미')
example('철수', '영미', '진수', '나영', '태현')
철수 영미 ()
철수 영미 ('진수', '나영', '태현')

위 예제에서 stuff는 인수가 나열된 튜플입니다. 우리는 for 가등을 이용하여 인수를 활용해볼 수 있을 것입니다.


위치 인수와 키워드 전용 인수

이 용어는 전문가를 위한 파이썬의 번역본을 그대로 가져왔습니다.

위치 인수(positional argumnet) 란 함수에게 인수를 전달할 때 첫 번째 위치, 두 번째 위치 등 위치 기반으로 전달되는 인수입니다. 모든 위치 인수는 키워드로서 전달할 수 있습니다. 키워드로서 전달하는 방법은 함수 호출 시 인수를 적을 때 인수명=값과 같이 작성하면 됩니다. 아래 예시를 참고해주세요.

def example(apple, banana):
    print(apple, banana)
example('철수', '영미')
example(banana='철수', apple='영미')
철수 영미
영미 철수

키워드 인수와 위치 인수는 혼합하여 사용할 수 있습니다. 다만 함수 호출 시 키워드로서 인수 전달은 반드시 위치 인수 뒤에 있어야 합니다. 다음 예제를 참조해주세요.

def example(apple, banana):
    print(apple, banana)
# example(banana='철수', '영미')
# 설명 : 에러입니다. 키워드 인수 전달은 반드시 위치 인수보다 뒤에 있어야 합니다.

# example('철수', apple='영미')
# 설명 : 에러입니다. 첫번째 두번째 모두 apple 인수를 가리키고 있습니다.

example('철수', banana='영미') 
# 설명 : 성공입니다.
철수 영미

키워드 전용 인수(keyword-only argumnet) 는 결코 위치 기반으로 전달될 수 없는 인수를 뜻합니다. 특징은 다음과 같습니다.

  • 키워드 전용 인수로 설정하는 방법은 크게 어렵지 않습니다. 별표(*) 뒤에, 즉 가변 위치 인수 뒤의 것들은 모두 키워드 전용이 됩니다.
  • 기본값(default)를 지정해도 되고 지정하지 않아도 됩니다.
  • 위치 인수와 달리 기본값이 있는 것과 없는 것 사이의 순서는 상관이 없습니다.
def example(apple, banana, *stuff, magic='마술', car):
    print(apple, banana, stuff, car, magic)

# example('철수', '영미')
# 설명: 에러입니다. car을 무조건 지정해야 합니다.

# example('철수', '영미', '진수', '나영', '태현') 
# 설명: 에러입니다. 가변 인수는 모두 stuff로 들어가기 때문에 
# 마찬가지로 car이 지정되지 않았습니다.

example('철수', '영미', '진수', '나영', '태현', car='포르쉐') 
# 설명: 성공적입니다.
철수 영미 ('진수', '나영', '태현') 포르쉐 마술

가변 인수 없는 키워드 전용 인수

가변 인수 없이 키워드 전용 인수를 사용하고 싶다면, 별표(*)만 하나 들어간 인수를 설정해주면 됩니다.

def f(a, *, b):
    print(a + b)

f(1, b=2)
# f(3, 4) ## 에러입니다. b는 무조건 키워드로 접근해야 합니다.
3

키워드 전용 가변 인수

키워드 전용 인수 또한 가변 인수를 설정할 수 있습니다. 방법은 위치 가변 인수와 비슷한데, 별표(*) 하나가 아니라 두개(**)를 변수명 앞에 붙여주면 됩니다. 특징은 다음과 같습니다.

  • 함수 내에서 딕셔너리(dictionary) 로 제공됩니다.
  • 마찬가지로 기본값을 지정할 수 없습니다.
  • 마찬가지로 함수에 하나에 최대 하나만 존재합니다. def example(a, **b, **c):와 같이 정의하면 바로 에러가 발생합니다.
  • 위치 가변 인수와 함께 사용할 수 있습니다. def example(a, *b, **c):는 문제 없습니다.
  • 위치 가변 인수 뒤에 존재해야 합니다. def example(a, **b, *c):는 에러입니다.
  • 뒤에 키워드 전용 인수가 올 수 없습니다. def example(a, *b, **c, d=10)는 에러를 일으킵니다.
  • 함수를 호출할 때 가변 인수에 값이 하나도 전달되지 않아도 됩니다.

아래는 예시입니다.

def example(apple, banana, **stuff):
    print(apple, banana, stuff)
example('철수', '영미')

# example('철수', '영미', '민수')
# 설명 : 위치 인수는 가변 인수 없이 2개만 
# 받고 있으므로 '민수'는 갈 데가 없어서
# 에러가 발생합니다.

example('철수', '영미', smart='민수')
철수 영미 {}
철수 영미 {'smart': '민수'}

위치 전용 인수

2019년 10월 14일 업데이트 된 파이썬 3.8에서 새롭게 추가된 내용입니다. 기본적으로 인수는 위치 인수이고, 키워드를 통해서도 접근할 수 있다고 하였습니다. 하지만 위치로만 접근할 수 있고 키워드로는 접근할 수 없도록 제한하는 방법이 새로이 등장했습니다. 그것은 위치 인수 사이에 /라는 인수를 추가하는 것입니다. /를 기준으로 왼쪽에 있는 변수들은 모두 위치 전용 인수가 됩니다.

def f(a, b, /, c, d, *, e, f):
    print(a, b, c, d, e, f)
# a, b는 위치 전용 인수이고 c, d는 일반 위치 인수이고 e, f는 키워드 전용 인수입니다.

f(10, 20, 30, d=40, e=50, f=60)
# 올바른 사용입니다. 

f(10, b=20, c=30, d=40, e=50, f=60)
# 에러입니다. b는 키워드로 접근할 수 없습니다.

f(10, 20, 30, 40, 50, f=60)   
# 에러입니다. e는 위치 기반으로 접근할 수 없습니다.

위치 전용 인수는 일반 사용자보다는 라이브러리 설계자가 이용하도록 고안된 것이며 우리가 함수를 정의할 때 이를 사용하는 일은 드물 것입니다. 하지만 파이썬 표준에 포함된 만큼 어떤 라이브러리가 /를 사용한다고 했을 때 무슨 용도인지는 이해하여야 할 것이기에, 짧게나마 소개해봤습니다.


순서

함수를 정의할 때 인수의 순서는 명확하게 정리되겠죠? 왼쪽에서부터 오른쪽까지 다음 순서입니다.

  1. 위치 인수 (기본값 X)
  2. 위치 인수 (기본값 O)
  3. / (위치 인수들 어딘가에 존재)
  4. 위치 가변 인수 (*)
  5. 키워드 전용 인수 (기본값 유무 상관 없음)
  6. 키워드 전용 가변 인수 (**)

다음은 함수를 호출할 때의 순서입니다.

  1. 키워드 없이, 차례대로
  2. 키워드 있게, 순서 상관없이

기본 값 없이 선택사항으로 만들고 싶을 때

기본 값을 특별히 만들고 싶지는 않지만 선택사항으로 두어 인수를 빼먹어도 에러가 나지 않도록 프로그램을 만들고 싶습니다. 그렇다면 None 객체를 활용합시다. 다음은 예시입니다.

def example(a, b, c=None):
    print(f'a({a})와 b({b})는 필수입니다.')
    if c is not None:
        print(f'c 값이 들어왔습니다. ==> {c}')
    else:
        print('c 값이 들어오지 않았습니다.')

example(10, 20)
example(300, 400, 500)
a(10)와 b(20)는 필수입니다.
c 값이 들어오지 않았습니다.
a(300)와 b(400)는 필수입니다.
c 값이 들어왔습니다. ==> 500

문서 읽어보기

print

우리가 밥먹듯이 쓰는 print 함수의 문서를 찾아봅시다. 정의는 다음과 같습니다.

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False):
    # 내용

첫번째로 가변 인수 objects가 등장합니다. 즉 우리가 print('안녕', '파워', '맨~', '커피')와 같이 인수를 무제한으로 넣어도 잘 작동됨을 확인할 수 있습니다. sep, end, file, flush기본값이 있는 키워드 전용 인수 임을 확인할 수 있습니다. 기본값이 있기 때문에 따로 지정해주지 않아도 알아서 잘 작동했구나 알 수 있습니다.

인수가 각각 어떤 역할을 하는지 좀 더 문서를 자세히 살펴봐야겠습니다. 여러분께서 직접 찾아보셔도 되지만, fileflush는 출력 방식과 관련된 내용이라 어려우니 패스하고 sepend가 어떤 역할인지만 살펴봅시다.

  • sep : print의 인수로 여러 개가 들어왔을 때 그것들을 구분할 문자
  • end : print가 모든 문자열의 출력을 마치고 마지막으로 출력할 문자

위에서 살펴 보았듯 sep에는 공백 하나가 기본값으로 되어 있고, end는 줄바꿈으로 되어있습니다. 직접 내용을 설정해서 호출해 볼까요?

print('안녕','하세요','반갑','습니다','하하',sep='(^o^)',end=' 뽜이야~')
print('  줄이 안바뀌었네요..?')
안녕(^o^)하세요(^o^)반갑(^o^)습니다(^o^)하하 뽜이야~  줄이 안바뀌었네요..?

어떤가요? 문서가 좀 더 잘 이해되시나요?


pandas.read_excel

pandas.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, usecols=None, squeeze=False, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skiprows=None, nrows=None, na_values=None, keep_default_na=True, verbose=False, parse_dates=False, date_parser=None, thousands=None, comment=None, skip_footer=0, skipfooter=0, convert_float=True, mangle_dupe_cols=True, **kwds)

어마어마하게 기네요.. io는 필수로 넣어야 할 위치 인수임을 바로 확인할 수 있고, 나머지는 선택 사항인 인수들입니다. 그 다음에는 마지막으로 kwds라는 키워드 전용 가변 인수 가 등장합니다. 설명은 따로 다시 찾아봐야 하겠지만, 함수 사용법을 일차적으로 이해하는 데 큰 의의가 있다는 것을 명심해주세요!


여담

별표는 영어로 Asterisk 라고 합니다. 아스터리스크 라고 읽는지..는 잘 모르겠습니다 호호. 별표를 영어로 검색할 일이 있을 때 참고하도록 합니다.


연습 문제

  • 함수를 정의할 때 인수의 순서가 어떻게 되는가?
  • 인수의 기본값은 어떻게 지정하는가?
  • 함수를 호출할 때 키워드를 지정하는 방법은 무엇인가?
  • 가변 인수란 무엇인가?
  • 가변 인수를 함수 내에서 이용하려면 (값을 뽑아내려면) 어떻게 해야 하는가?
  • 키워드 전용 가변 인수는 무엇인가?
  • 키워드 전용 가변 인수를 함수 내에서 이용하려면 (값을 뽑아내려면) 어떻게 해야 하는가?

프로그래밍 문제

argparse

argparse 모듈은 파이썬 스크립트를 콘솔에서 실행시킬 때 명령행 인자를 더 편리하게 관리해주는 기능을 제공합니다. 단순한 문자열의 리스트로 들어오는 데이터를 유의미한 데이터로 쉽게 변환하는 데 그 의의가 있습니다. 기본적인 사용 흐름과 예시는 다음과 같습니다.

graph TD p1["python test.py data.xlsx --temp template.html<br>를 콘솔에 입력합니다."] p1 --> p2 p2["sys.argv에 문자열을<br> 담은 리스트 형태로<Br>데이터가 생성됩니다.<br>(공백으로 리스트의<br>항목이 구분됩니다.)"] p2 -.- s1["import sys<br>print(sys.argv)"] s1 -.-> s2["['test.py', 'foo', '--bar', 'data.xlsx']"] p2 --> p3["parser.parse_args()<br>를 통해 미리 작성된<br>설정을 바탕으로 sys.argv<br>를 읽고 데이터가 담긴<br>객체를 반환합니다."] a1["import argparse<br>parser = argparse.ArgumentParser(...)<br>를 통해 ArgumentParser 객체를 생성합니다."] a2["parser.add_argument(...)<br>를 통해 불러올 데이터를<br>미리 설정합니다."] a2 --> a2 a1 --> a2 a2 --> p3

argparse 모듈을 사용하는 흐름

그리고 test.py 파일을 아래와 같이 작성합니다.

import argparse
import sys
parser = argparse.ArgumentParser()
parser.add_argument('data')
parser.add_argument('-t', '--temp')
args = parser.parse_args()
print(sys.argv)
print(args)

그리고 콘솔에서 cd 명령을 통해 작업 디렉토리를 파이썬 코드가 있는 폴더로 옮깁니다. 예제의 경우에는 바탕화면에 저장되어 있으므로 cd desktop으로 하였습니다. 그 이후 python 명령으로 작성한 파일을 실행시킵니다.

PS C:\Users\tooth> cd desktop
PS C:\Users\tooth\Desktop> python test.py data.xlsx --temp template.html
['test2.py', 'data.xlsx', '--temp', 'template.html']
Namespace(data='data.xlsx', temp='template.html')

여기서 add_argument 메서드의 설명을 잠시 끌어와보겠습니다.

ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])

  • default : 해당 옵션의 기본 값을 지정합니다.
  • help : 해당 옵션의 도움말을 지정합니다.
  • choices : 해당 옵션의 선택가능한 리스트를 지정합니다. 예를 들어 ['red', 'black']이라고 지정하면 red, black 외의 문자열은 지정할 수 없습니다.
  • required : 해당 옵션의 필수 유무를 지정합니다. 기본적으로는 False 입니다.

(후략)


문제

  1. parser.add_argument('--name', default="Peter")는 어떻게 동작하는가?

  2. parser.add_argument('-d', '--data', required=True)는 어떻게 동작하는가?

  3. parser.add_argument('type', help="색깔을 정하세요", choices=['red', 'black', 'blue']) 는 어떻게 동작하는가?

  4. 데이터 엑셀 파일과 템플릿 HTML 파일을 인수로 받고자 한다. 데이터 엑셀 파일의 기본 값은 data.xlsx, HTML 파일은 template.html로 지정하고자 하고 이 인수를 필수로 받고자 한다. 그에 따라 add_argument 메소드를 적절히 호출하라.


  1. 프롤로그
  2. 개발 첫걸음
    1. 컴퓨터 구성요소 – 컴퓨터는 어떤 걸 할 수 있나?
    2. 개발과 관련된 용어
    3. 파이썬의 선택 – 왜 파이썬인가?
    4. 파이썬 설치 – Hello World 출력하기
    5. Visual Studio Code 의 편리한 기능
    6. REPL과 콘솔 창 – 파이썬 동작시키기
  3. 파이썬 기초
    1. 기초 입출력 – 소통하기
    2. 변수와 대입 – 기억하기
    3. 연산자 – 계산하기
    4. 조건문 – 분기를 만들기
    5. 반복문 – 비슷한 작업을 반복하기
    6. 반복문 코딩하기
    7. 변수와 리스트 – 비슷한 변수들을 묶기
    8. for, range – 리스트의 항목을 다루기
    9. 함수와 메소드의 호출 – 편리한 기능 이용하기
    10. 모듈 설치와 사용 – 유용한 기능 끌어다 쓰기
    11. 문자열 – 텍스트 다루기
  4. 파이썬 중급
    1. 함수를 직접 만들기 – 자주 쓰는 기능을 묶기
    2. 딕셔너리, 튜플, 세트 – 변수를 다양한 방법으로 묶기
    3. 클래스와 객체 – 변수를 사람으로 진화시키기
    1. 상속 – 클래스를 확장하기
    2. 정체성과 동질성 – 객체의 성질
    3. 특별 메소드와 연산자 – 파이썬의 내부 작동방식 이해하기
    4. 다양한 함수 인수 – 유연한 함수 만들기
    5. 슬라이싱 – 리스트 간편하게 접근하기
    6. 지능형 리스트(List Comprehension) – 리스트 갖고 놀기
    7. namedtuple - 데이터 묶음 손쉽게 만들기
    8. 조건 표현식 (Conditional Expression) - 간단한 분기 나타내기
    9. 코드 스타일 - 코드의 일관성 유지하기
    10. 명령문, 표현식 – 문법을 이루는 것들
    11. 본격적인 검색 해보기
  5. 파이썬 고급
    1. 일급 함수 다루기
    2. NotImplementedError와 NotImplemented
    3. 어노테이션 – 수월하게 프로그래밍하기
    1. 내장 함수 톺아보기
    2. 예외와 에러 – 예상치 못한 상황에 대응하기 (v0.1)
    3. 변수의 범위 – 이름 검색의 범위
  6. 파이썬 심화
    1. 시퀀스와 반복자 – 반복과 순회를 자유자재로 다루기
    2. 데코레이터 – 함수의 기능을 강화하기
    3. 프로퍼티
    4. 제너레이터
    5. async와 await
    6. 객체로서의 클래스 – 클래스를 동적으로 정의하기
  7. 파이썬 프로젝트 실습
    1. 원카드 게임 만들기 (1)
    2. 원카드 게임 만들기 (2)
    3. 원카드 게임 만들기 (3) (작성중)
    4. 턴제 자동 전투 게임 만들기 (작성중)
  8. 실전 (파이썬 외적인 것들)
    1. 정규표현식 – 문자열을 검색하고 치환하기 (작성중)
    2. 유니코드 – 컴퓨터에서 문자를 표기하는 방법
    3. html, css, 인터넷 – 자동화 첫 걸음 내딛기
    4. 네트워크 – 인터넷으로 통신하는 방법
    5. 문서 – 문맥을 읽어보기

4 thoughts on “파이썬 강좌 – 다양한 함수 인수 ~ 유연한 함수 만들기

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다

Scroll to top