본문 바로가기
코딩 연습/코딩배우기

파이썬 실천 기술 #03 - 함수

by good4me 2021. 5. 25.

goodthings4me.tistory.com

 

효율적 개발로 이끄는 파이썬 실천 기술 - 함수

(참고용으로 사용할 부분만 간략하게 정리)

함수

  • 파이썬의 모든 데이터는 객체라고 함(클래스나 인스턴스, 함수도 객체)
  • 함수를 정의하면 함수명의 이름과 똑같은 함수 객체(function object)가 만들어짐
  • 함수 객체를 다른 함수의 인수(argument)로 전달하거나 변수에 대입 가능
  • 함수명에 ()를 붙여 호출하고 처리(실행)한 결과를 반환값으로 호출자에게 반환
# 함수는 객체, function 타입
def print_page(content):
    print(content)

print(print_page)  # 함수 객체 출력 (함수명 print_page == 변수)
print_page('인수 있는 함수임')  #  ()를 붙여 호출, 인수 있음
print(print_page('no content'))  # 파이썬의 함수는 return 문이 없어도 내부적으로 None 반환

print(type(print_page))  # function 타입
f = print_page  # 함수 객체를 변수 f에 대입
f('인수 있는 함수')

# 다른 함수의 인수나 반환값으로 사용
def print_title(printer, title):
    print('#' * 10)
    printer(title.upper())  # printer는 함수 객체
    print('#' * 10)

print_title(print_page, 'Python')


[결과]
<function print_page at 0x7f180e3ce830>
인수 있는 함수임
no content
None
<class 'function'>
인수 있는 함수
##########
PYTHON
##########

 

# 함수 인수에 기본값 지정
def increment(page_num, last=10): 
    next_page = page_num + 1
    if next_page <= last:
        return next_page
    raise ValueError('Invalid argument')

try:
    print(increment(8, 10))
    print(increment(9))    
    print(increment(10, 12))
    print(increment(10))
except ValueError as e:
    print(f'에러: {e}')


[결과]
9
10
11
에러: Invalid argument

 

# 기본값의 함정
from datetime import datetime

def print_page(content, timestamp=datetime.now()):
    print(content)
    print(timestamp)

print(print_page('my content'))
print(print_page('my_content2'))
# 출력값이 동일한 이유 : 표현식이 함수가 정의될 때 한 번 값이 구해지고, 호출마다 같은 (미리 계산된) 값이 사용됨


[결과]
my content
2021-05-25 11:01:00.894542
None
my_content2
2021-05-25 11:01:00.894542

good4me.co.kr

# 기본값에 현재 시각, 빈 리스트, 빈 딕셔너리 등의 가변객체를 지정하지 말고 None 사용하는 것이 좋음
from datetime import datetime

def print_page(content, timestamp=None):
    if timestamp is None:
        timestamp = datetime.now()
    print(content)
    print(timestamp)

print(print_page('my content'))
print(print_page('my_content2'))


[결과]
my content
2021-05-25 11:02:30.738843
None
my_content2
2021-05-25 11:02:30.746272
None

 

# 길이가 변하는 위치 및 키워드 인수
def print_page(*args, **kwargs):
    for content in args:
        print(content)
    for key, value in kwargs.items():
        print(f'{key}: {value}')

print_page('content1', 'content2', 'content3', published=2019, author='hey')


[결과]
content1
content2
content3
published: 2019
author: hey

 

# 인수 리스트 언팩 - 함수 호출 시 리스트나 딕셔너리의 값을 인수로 전달(리스트나 튜플은 * 연산자, 딕셔너리는 ** 연산자)
def ex_listunpack(one, two, three):
    print(one)
    print(two)
    print(three, '\n')

contents = ['my content', 'content2', 'content3'] # 전달 인수의 개수 맞춤
ex_listunpack(*contents) 

def ex_dictunpack(content, published, author):
    print(content)
    print(published)
    print(author)

footer = {'published': 2019, 'author': 'hss'}
ex_dictunpack('my content', **footer)


[결과]
my content
content2
content3 

my content
2019
hss

 

# lambda 식 - 1행의 이름 없는 함수 작성, 함수 인수로 함수 객체를 전달할 때 자주 사용
# 구문 lambda 인수1, 인수2, ...: 반환값이 되는 식

def increment(num):
    return num + 1

# 위 함수를 lambda 식으로 하면
increment = lambda num: num + 1
print(increment)
print(increment(3))

# 내장 함수 filter()의 첫 인수로 lambda 함수 사용
nums = ['one', 'two', 'three', 'four']
filtered = filter(lambda x: len(x) == 3, nums)
print(filtered)
print(list(filtered))


[결과]
<function <lambda> at 0x7f180a975e60>
4
<filter object at 0x7f180a936690>
['one', 'two']

 

# 타입 힌트 : 정적타입언어와 같이 함수의 인수와 반환값에 타입 정보를 붙이는 기능이지만, 
# 애너테이션 속성(annotations)에 저장될 뿐, 실행 시에 타입 체크 수행은 안함

def decrement(page_num: int) -> int:  # 인수 및 반환값 타입 정보
    prev_page: int  # 타입 정보 붙여 변수 선언 가능
    prev_page = page_num - 1
    return prev_page

print(decrement(2))
print(decrement(2.0))  # 실행 시 타입 체크 안하기 때문에 에러 발생X
print(decrement.__annotations__)  # 타입 정보 저장 확인


[결과]
1
1.0
{'page_num': <class 'int'>, 'return': <class 'int'>}

 

[참고/출처] 효율적 개발로 이끄는 파이썬 실천 기술 - 파이썬에 숨겨진 힘을 이용해 개발 효율을 높이자!

 

댓글