뒤죽박죽 데이터분석 일기장
[Python] [강의 3일차] 함수 본문
이번 포스트에서는 함수에 대해서 복습해보려고 합니다.
본격적으로 함수 내용 들어가기 전에 저번 수업 시간에 배웠던 반복문과 조건문을 가지고 로또 번호 생성기 프로그램을 만들어 보도록 하겠습니다.
로또 번호 생성기
1. 1 ~ 45의 랜덤한 숫자 6개 출력
2. 숫자 6개 중에 중복 데이터가 없어야 함
import random
# 1. 로또번호 저장 변수 생성
lotto = []
# 2. 아래의 코드 반복 : while
while True:
# 2-1. 1 ~ 45 랜덤한 숫자 출력 후 저장 : random_number : random.randint()
random_number = random.randint(1, 45)
# 2-2. lotto 리스트에 random_number 없으면, random_number를 lotto 변수에 추가 : list.append()
# if random_number not in lotto:
# lotto.append(random_number)
# 2-2. random_number를 lotto 변수에 추가 : list.append()
lotto.append(random_number)
lotto = list(set(lotto))
# 2-3. lotto의 데이터 갯수가 6개 이상이면 반복 중단 : if, len(), break
if len(lotto) >= 6:
break
# 3. 로또번호 출력 : print()
lotto.sort()
print(lotto)
이번 프로그램은 새롭게 append()를 사용해서 계속해서 생성되는 랜덤 숫자를 더해줬습니다.
또한 set()의 중복되는 값을 삭제해 주는 기능을 이용해 중복되지 않은 숫자를 출력할 수 있었습니다.
매번 이런 프로그램을 작성하기 쉽지는 않습니다. 그래서 우린 자동 로또 번호 생성 프로그램을 함수에 저장해서 계속 사용하려고 합니다.
def display_lotto():
lotto = []
while True:
random_number = random.randint(1, 45)
lotto.append(random_number)
lotto = list(set(lotto)) #set 함수로 중복값 제거
if len(lotto) >= 6:
break
lotto.sort()
print(lotto)
# 함수호출 (코드실행)
display_lotto()
결과:
바로 위의 코드처럼 기존에 있던 프로그램일 넣어서 함수선언을 할 수 있습니다. 그러고 저장된 함수를 입력해 6개의 랜덤 숫자를 출력하는 프로그램을 완성할 수 있습니다.
그런데 갑자기 투자자 분들이 이 프로그램에 추가적인 기능을 넣고 싶다고 합니다! (농담입니다)

어떤 기능일까요? 함수를 입력시에 번호가 출력되는 것은 좋은데 출력할 수 있는 숫자의 개수와 범위를 커스텀 할 수 있으면 좋겠다고 합니다.
import random
# 함수선언(코드작성)
def display_lotto(count=6, until=45):
lotto = []
while True:
random_number = random.randint(1, until)
lotto.append(random_number)
lotto = list(set(lotto)) #set 함수로 중복값 제거
if len(lotto) >= count:
break
lotto.sort()
print(lotto)
# 로또번호출력 : 6개
display_lotto(6, 100) # 6 : argument
# 로또번호출력 : 7개
display_lotto(7)
# 기존프로그램
display_lotto()
결과:
제안해 주신대로 출력할 수 있는 숫자의 개수와 범위를 직접 입력해서 조정할 수 있게 함수를 수정했습니다.
괄호 안에 Parameter 넣어서 함수 안에 알고리즘에 출력 시킬 수 있습니다.
위의 코드의 경우 기본 parameter는 2개이고 1번 parameter는 숫자의 개수 그리고 2번 parameter는 범위입니다.
하지만 현재 default paramter가 각각 6으로 설정되어 있는걸 확인할 수 있습니다.
이 뜻은 아무런 parameter를 입력하지 않으면 default parameter로 실행된다는 뜻입니다.
* 함수 안에는 몇 가지 명령어들이 사용됩니다. 이번에는 그 명령어들의 사용법을 하나 하나 설명해 보겠습니다.
return
return은 함수를 호출해서 결과 데이터를 변수에 저장할 때 사용됩니다.
혹은 함수의 코드를 중단할 때 사용됩니다.
우선, 함수를 호출해서 결과 데이터를 변수에 저장하는 예시를 확인해 보겠습니다.
위의 코드는 return을 사용하지 않고 아래의 코드는 return을 사용한 경우입니다.
def plus1(n1, n2):
print(n1 + n2)
def plus2(n1, n2):
return n1 + n2
result1 = plus1(1, 2)
result2 = plus2(2, 3)
print(result1, result2)
결과:
↑
이렇게 result 1의 결과값은 none으로 출력되고 result 2는 값이 출력되어 있습니다. 쉽게 말하자면 result 1의 경우 함수는 그저 print 내용을 출력하는 것이지 값을 저장하는 것은 아닙니다.
이번에는 실제로 파이썬에 저장되어 있는 함수에 return 값이 저장되어 있는 경우와 그렇지 않은 경우를 비교해 보겠습니다.
1. 리턴이 있는 함수 : str.upper( )
data = 'python'
result1 = data.upper()
print(data, result1)
결과:
2. 리턴이 없는 함수 : list.sort( )
# 리턴이 없는 함수 : list.sort() #리턴이 없으면 결과값을 저장하지 않는다. /기존 데이터가 변함
data = [1, 3, 2]
result = data.sort()
print(data, result)
결과:
정리
특징 | ||
리턴이 있는 함수 : str.upper( ) | result 값에 저장됨 | 기존 데이터가 변하지 않음 |
리턴이 없는 함수 : list.sort( ) | result 값에 저장되지 않음 | 기존 데이터가 변함 |
이번에는 return을 이용해서 함수의 코드 실행을 중단 시키는 걸 알아보겠습니다.
# 함수의 코드 실행 중단
def echo(msg, count=3):
for idx in range(count):
if idx >= 5:
return
print(msg)
print('Done')
# 함수 실행
echo('python', 7)
결과:
위의 코드를 분석해보겠습니다.
1. 함수가 실행됬을때 문자열 'python'은 msg에 그리고 숫자 7은 count로 할당됬습니다.
2. for 구문에서 range(count) 즉, range(7)로 [0, 1, 2, 3, 4, 5, 6]의 숫자가 차례차례 idx에 할당됩니다.
3. 아래의 if 구문에서는 idx 값이 5 이상일 때 return 한다고 합니다.
4. 아래의 print 구문을 무시하고 다시 for 구문으로 돌아가는 것을 의미합니다.
5. idx가 5보다 작을 때는 msg에 해당되는 값을 계속해서 출력합니다.
6. 결론은 idx가 5에 해당될 때까지는 계속 msg 값을 출력합니다. 따라서 해당되는 구문이 5번 출력되었습니다.
이번엔 함수로 여러 데이터를 출력해 보겠습니다.
1. 리스트 형태로 출력
# 여러개의 데이터를 리턴
def calc(n1, n2):
result = [n1 + n2, n1 - n2]
return result
result = calc(3, 1)
result
결과:
리스트 형태로 출력됩니다.
2. 튜플 데이터로 출력후 할당하기
# 여러개의 데이터를 리턴
def calc(n1, n2):
return n1 + n2, n1 - n2 #튜플 데이터이므로
plus, minus = calc(3, 1) #햘당 가능
print(plus, minus)
print(type(plus), type(minus))
결과:
괄호가 없는 경우에는 튜플 데이터 값으로 출력됩니다. 따라서 개수에 맞는 할당자를 지정해 주면 각각 int형으로 저장됩니다.
3. 튜플 데이터로 출력후 할당하기 - 원하는 값만 출력하기
# 여러개의 데이터를 리턴
def calc(n1, n2):
return n1 + n2, n1 - n2
plus, _ = calc(3, 1) #plus만 필요하다면 low dash로 바꾸어서 plus 값만 출력 가능
plus
결과:
출력을 원하지 않은 값을 low dash로 변환시켜 원하는 값만 출력시키면 됩니다.
docstring
docstring은 함수의 설명을 작성한 문서입니다.
보통 함수선언코드 바로 아래에 멀티라인 문자열로 구성되어 있습니다.
help( ) 함수로 docstring을 출력할 수 있습니다.
예를 들어 두 숫자를 더하는 함수의 docstring을 만들고 싶다면
def plus(n1, n2):
'''
This function is to plus two numbers.
parameter
--------
n1 : int, float : first number
n2 : int, float : second number
return
------
n1 + n2 : int, float
'''
return n1 + n2
이렇게 ''' , ''' 를 이용해서 함수 선언 중간에 docstring을 넣을 수 있습니다.
docstring 내용을 확인하고 싶다면 help(함수)을 입력하면 확인할 수 있습니다.
보통 docstring에는 3가지 내용이 들어간다고 합니다.
첫번째, 이 함수가 어떤 함수인지 대략적인 설명
두번째, paramter 종류
세번째, 만약 return 값이 있다면 return 되는 값은 어떤 값인지?
보통 모르는 함수가 나온다면 help 함수를 이용해서 docstring 내용을 확인하면 함수에 대한 내용을 쉽고 자세히 알 수 있다고 합니다.

*args / **kwargs (Argument and Keyword argument)
이번에는 argument의 개수에 상관없이 함수를 실행하는 방법에 대해서 알아보겠습니다.
*args : 여러개의 argument를 튜플 데이터타입으로 받아줌
** kwargs : 여러개의 keyword argument를 딕션너리 데이터타입으로 받아줌
TMI : *args 와 ** kwargs는 바꿀 수 있는 변수입니다. 하지만 업계에서는 이 명칭을 주로 사용한다고 합니다.
def plus(*args, **kwargs): # 파라미터에 컬렉션 데이터 타입을 받아줌 : 식별자1개, 데이터n개
print(type(args), args)
print(type(kwargs), kwargs)
# return n1 + n2
# 키워드 아규먼트는 키워드가 없는 아규먼트 뒤에 사용
# 디폴트 파라미터는 디폴트 값이 없는 파라미터 뒤에 사용
plus(1, 2, 3, 4, 5, n1=10, n2=30) # 여러개의 아규먼트
결과:
plus 함수에 숫자 1, 2, 3, 4, 5를 입력하고 키워드 n1=10, n2=20 을 입력했을때
1서부터 5는 튜플로 그리고 나머지 키워드들을 딕션너리로 출력되었습니다.
특징:
# 파라미터 사용시 : 여러개의 아규먼트 → 컬렉션 데이터타입(tuple, dict)으로 묶어줍니다.
# 아규먼트 사용시 : 컬렉션 데이터 타입(list, tuple, dict) → 여러개의 아규먼트로 풀어줍니다.
파라미터 사용시 예시에 대해서 보여드리겠습니다.
함수:
def echo(*args, **kwargs):
print(type(args), args)
print(type(kwargs), kwargs)
1. *args 를 파라미터에서 이용시
data = [1, 2, 3]
echo(data) # echo([1,2,3]) > 아규먼트 : 1개, 데이터타입 : 리스트
echo(*data) # echo(1,2,3) > 아규먼트 : 3개, 데이터타입 : 정수
# *를 붙이면 리스트를 풀어서 여러개의 아규먼트로 만들어 줄 수 있다.
결과:
리스트 데이터를 튜플로 풀어줘 3개의 아규먼트를 생성한다.
2. **kwargs를 파라미터에서 이용시
data = {'num1': 10, 'num2': 20}
echo(data) # echo({'num1': 10, 'num2': 20}) > 아규먼트 1개, 데이터타입 : 딕셔너리
echo(**data) # echo(num1=10, num2=20) > 키워드 아규먼트 2개, 데이터타입 : 정수
결과:
1개 였던 딕션너리 아규먼트를 2개의 정수 아규먼트로 생성한다.
정리하자면
예시를 들어서 데이터 베이스 접속 함수를 나타내 보겠습니다.
# 데이터베이스 접속 함수
def connect(**kwargs):
print('connect : ', kwargs['host'], kwargs['user'], kwargs['pw'])
data = {'host': '1.2.3.6', 'user': 'python', 'pw': '1234'}
# connect(host=data['host'], user=data['user'], pw=data['pw'])
connect(**data)
결과:
이렇게 딕션너리 형태로 된 데이터를 **이용해 바로 함수에 넣을 수 있습니다.
Scope
이번에는 scope 개념에 대해서 복습해보려고 합니다.
간단하게 정리하자면
파이썬에서는 함수 밖 영역의 전역영역 : global, 그리고 함수 안 영역의 지역영역 : local이 존재합니다.
# 실수 할만한 코드 3
data = 10 #global 영역
def change():
data = 20 #로컬 영역
change()
print(data)
결과:
출력되는 data 값이 20일 것이라고 생각하는 경우가 많을 것입니다! 왜냐하면 함수 안에서 data 값에 숫자 20이 할당됬기 때문인데요.
하지만 출력되는 값은 10입니다.
이 이유는 코드 서두의 data = 10은 함수 바깥 영역에 저장됬습니다. 그리고 함수 안에서는 data = 20이라고 할당을 했죠. 하지만 이는 서로 다른 영역 입니다. 그래서 함수 안에서 같은 data 값에 20을 할당하더라도 숫자가 변하지 않는 이유는 서로 다른 영역에 있기 때문이죠.
이를 해결하기 위해서
# global : 지역영역에서 전역영역의 변수사용 방법
data = 10 #global 영역
def change():
global data #글로벌 영역에 있는 변수를 지역영역의 변수로 가져옵니다.
data = 20 #로컬 영역
change()
print(data)
결과:
위의 코드처럼 global data 문을 이용해서 글로벌 영역에 있는 변수를 지역영역의 변수를 함수 안으로 가져오면 data 값을 변경할 수 있습니다.
반대로, 지역영역에서의 변수를 글로벌영역의 변수로 사용하는 방법도 있습니다. 바로 return 을 사용하면 되는데요.
# return: 전역영역에서 지역영역의 변수 사용하는 방법
data = 10
def change():
data = 20
return data
data = change()
print(data)
결과:
위 처럼 return data를 통해서 data 값이 20이라고 할당됬다는 걸 return을 통하면 글로벌 영역에서 사용 가능합니다.
lambda 함수
이번에는 람다 함수에 대해서 알아보려고 합니다.
람다 함수는 일회성 함수로 간단한 함수(파라미터, 리턴)를 함수 선언 없이 사용 가능합니다.
그러고 메모리가 절약되고 가독성이 증가된다는 장점을 가지고 있습니다.
람다 함수에 대해 설명하기 전에 이중함수에 대해서 설명하려고 합니다.
def plus(n1, n2):
return n1 + n2
def minus(n1, n2):
return n1 - n2
def calc(func, n1, n2): # func:plus
return func(n1, n2)
첫번째, 두번째 코드는 더하기 그리고 뺄셈을 함수화한것입니다. 그러고 세번째 코드에는 func이라는 값이 들어가 있는데 이는 함수 안에 원하는 특정 함수를 집어넣어서 실행 시킬 수 있습니다.
예를 들어
calc(plus, 1, 2), calc(minus, 1, 2)
결과:
여기서 알고 가야할 것은 function의 데이터 타입은 함수라는 것입니다.
자. 이제 람다 함수에 대해서 알아볼 건데요.
# lambda 함수 : 간단한 함수를 함수 선언 없이 사용 가능
func = lambda n1, n2: n1 + n2
func(1,2)
위의 코드와 같이 람다 함수는 간단하게 함수 선언이 한 줄로 가능합니다.
또 다른 예시는
# 저장공간 1칸 사용
def calc(func, n1, n2):
return func(n1, n2)
calc(lambda n1, n2: n1 + n2, 1, 2), calc(lambda n1, n2: n1 - n2, 1, 2)
결과:
두 개의 parameter을 가지고 특정 function을 실행하는 function을 람다를 이용해 손 쉽게 표현할 수 있습니다.
TMI: 람다 함수는 데이터 전처리 시에 많이 사용된다고 합니다!
List comprehension
이번에는 List comprehension이라는 개념을 알아볼건데요.
우선 0 - 9 까지의 데이터에서 홀수만 뽑아서 제곱한 결과를 리스트로 출력하는 프로그램을 만들어 보겠습니다.
# 0~9 까지의 데이터에서 홀수만 뽑아서 제곱한 결과를 리스트로 출력
result = []
for number in range(10):
if number % 2:
result.append(number ** 2)
result
List comprehension이란 이런 간단한 반복문 조건문을 사용해서 리스트 데이터를 만들 때 사용하는 문법입니다.
주로 리스트 데이터를 필터링 하거나 데이터를 변경할 때 사용됩니다.
List comprehension으로 한 줄로 줄여보겠습니다.
result = [number ** 2 for number in range(10) if number % 2] #뒤의 조건문이 먼저 실행되서 앞의 명령문을 실행해 list를 append 합니다.
result
결과:
성공적으로 줄일 수 있었는데요.
List comprehension을 쉽게 만들기 위해서는 우선 조건물을 먼저 입력하는 것이 중요합니다.
1. for number in range(10) if number % 2
이렇게 10개의 숫자 안에서 숫자가 홀수일 때 라는 조건문입니다.
2. 그러고 앞에 이 조건에 맞는 변수들에 대한 명령어를 적으면 끝납니다.
이번에는 함수와 List comprehension을 응용하여
Kim 씨 성을 가진 이름을 연령대로 데이터를 바꾸어 리스트로 출력해 보겠습니다.
names = ['kim python(23)', 'lee notebook(32)', 'kim macbook(47)']
def ages(data):
return data[:-3] + str(int(data[-3:-1]) // 10 * 10) + ')'
names_kim = [
ages(name)
for name in names
if name.split(' ')[0] == 'jang'
]
names_kim
결과:
처음에 문자열에 나이를 인식하고 문자열 안에 있는 나이를 연령대로 표현해 줄 수 있도록 변환해 주는 함수를 입력합니다.
그러고 List comprehension을 사용해서 해당되는 성일 때 값을 출력할 수 있게 한 줄로 표현해 줄 수 있습니다.
map 함수
map 함수의 정의는 iterable ( 반복 가능한 ) 한 데이터의 모든 value에 특정 함수를 적용한 결과를 리스트로 출력하는 함수입니다.
이전에 List comprehension을 설명했을때 작성했던 코드를 예시로 들어보겠습니다.
names = ['kim python(23)', 'lee notebook(32)', 'kim macbook(47)']
def ages(data):
return data[:-3] + str(int(data[-3:-1]) // 10 * 10) + ')'
list(map(ages, names))
결과:
map 함수에서는 (적용시킬 함수, 적용시킬 요소들)를 넣어 function을 실행시킬수 있습니다.
이번에는 조금 더 나아가서 두 가지 리스트를 가지고 map 함수에 넣어볼것이다.
names1 = ['kim python(23)', 'lee notebook(32)', 'kim macbook(47)']
names2 = ['kim py(33)', 'lee note(52)', 'kim book(87)']
def ages(*args):
return [data[:-3] + str(int(data[-3:-1]) // 10 * 10) + ')' for data in args]
print(list(map(ages, names1, names2)))
결과:
*args 를 사용해 두 리스트가 각 각 한 쌍이 되어서 출력되는 것을 확인할 수 있다.
'Python' 카테고리의 다른 글
[Python] [5일차] Class 파트 2 (2) | 2023.01.06 |
---|---|
[Python] [4일차] Class 파트 1 (0) | 2023.01.05 |
[Python] [2일차] 조건문, 반복문 (2) | 2023.01.03 |
[Python] [2일차] 데이터 Skill 비교, 연산자 (0) | 2023.01.03 |
[Python] [1일차] 얕은복사, 깊은복사, 문자열 데이터 활용 (0) | 2023.01.02 |