제어문
if, elif, else (조건문)
if와 else는 조건이 참인지 거짓인지 판단하는 파이썬 선언문(Statement)이며, elif는 else내의 if를 중첩해야 할 때 사용한다.
조건 표현식
In [3]: if is_holiday:
...: print('Good')
...: else:
...: print('Bad')
...:
Bad
중첩 조건표현식
In [4]: vacation = 7
In [6]: if vacation >= 7:
...: print('Good')
...: elif vacation >= 5:
...: print('Normal')
...: else:
...: print('Bad')
...:
Good
In [8]: print('Good') if vacation >= 7 else print('Normal') if vacation >= 5 else print('Bad')
Good
for문 (조건에 따른 순회)
기본형태
시퀀스형 데이터를 순회하고자 할 때 사용한다.
# for 항목 in 순회가능(iterable)객체:
# <항목을 사용한 코드>
# 숫자 시퀀스 생성 (range)
# iterable 객체를 반환
In [9]: for i in range(5):
...: print(i)
...:
0
1
2
3
4
In [10]: for x in range(1, 10, 3):
...: print(x)
...:
1
4
7
# iterable 객체로 문자열, 튜플, 딕셔너리, 셋 등이 있다.
# 리스트
In [11]: champion_list = ['lux', 'ahri', 'ezreal', 'zed']
In [12]: for champion in champion_list:
...: print(champion)
...:
lux
ahri
ezreal
zed
# 딕셔너리
In [13]: champion_dict = {
...: 'lux': 'abc',
...: 'ahri': 'def',
...: 'ezreal': 'ghi',
...: 'zed': 'jkl',
...: }
# 딕셔너리 키를 순회할 때
In [14]: for champion in champion_dict:
...: print(champion)
...:
ahri
lux
ezreal
zed
In [15]: for champion in champion_dict.keys():
...: print(champion)
...:
ahri
lux
ezreal
zed
# 딕셔너리 값을 순회할 때
In [16]: for champion in champion_dict.values():
...: print(champion)
...:
def
abc
ghi
jkl
# 딕셔너리 키/값 모두 순회할 때
In [17]: for champion in champion_dict.items():
...: print(champion)
...:
('ahri', 'def')
('lux', 'abc')
('ezreal', 'ghi')
('zed', 'jkl')
중첩
# 구구단 2단부터 9단까지 출력
In [17]: for i in range(2, 10):
...: for j in range(2, 10):
...: print('{} x {} = {}'.format(i, j, i*j))
In [18]: for i in range(2, 10):
...: print('= {} 단 ='.format(i))
...: for j in range(2, 10):
...: print('{} x {} = {}'.format(i, j, i*j))
...: print('\n')
...:
중단하기 (break)
데이터를 순회하던 중, 특정 조건에서 순회를 멈추고 반복문을 빠져나갈 때 사용한다.
# 구구단 2단부터 3단까지 출력
In [21]: for i in range(2, 10):
...: print('= {} 단 ='.format(i))
...: for j in range(2, 10):
...: print('{} x {} = {}'.format(i, j, i*j))
...: if i == 3:
...: break
건너뛰기 (break)
데이터를 순회하던 중, 반복문을 중단하지 않고 다음 반복으로 건너뛸 때 사용한다.
# 구구단 4단을 제외한 2단부터 9단까지 출력
In [22]: for i in range(2, 10):
...: if i == 4:
...: continue
...: print('= {} 단 ='.format(i))
...: for j in range(2, 10):
...: print('{} x {} = {}'.format(i, j, i*j))
여러 시퀀스 동시순회 (zip)
# zip으로 묶은 시퀀스 중,
# 가장 짧은 시퀀스가 완료되면 순회종료
In [23]: fruits = ['apple', 'banana', 'melon']
In [24]: colors = ['red', 'yellow', 'green', 'purple']
In [26]: for fruit, color in zip(fruits, colors):
...: print('fruit:', fruit, ' color:', color)
...:
fruit: apple color: red
fruit: banana color: yellow
fruit: melon color: green
# 튜플로 반환
In [28]: for item in zip(fruits, colors):
...: print(item)
...: print(type(item))
...: print(item[0])
...: print(item[1])
...:
('apple', 'red')
<class 'tuple'>
apple
red
('banana', 'yellow')
<class 'tuple'>
banana
yellow
('melon', 'green')
<class 'tuple'>
melon
green
# zip클래스 형태의 iterable 객체
In [34]: result = zip(colors, fruits)
In [35]: result
Out[35]: <zip at 0x10ab048c8>
In [36]: print(type(result))
<class 'zip'>
# 리스트 형태로 사용하려면 list()함수를 사용
In [37]: result_list = list(result)
In [38]: result_list
Out[38]: [('red', 'apple'), ('yellow', 'banana'), ('green', 'melon')]
In [39]: print(type(result_list))
<class 'list'>
While문 (반복문)
In [45]: count = 0
In [46]: while count < 4:
...: print(count)
...: count += 1
...:
0
1
2
3
컴프리헨션 (Comprehension)
iterable한 객체로부터 파이썬의 자료구조를 만드는 방법. 가독성과 사용성에서 이득을 얻을 수 있을 경우 항상 사용해준다.
한줄로 보기좋게 표현된다면, 가능한 사용하는 것이 좋다. (속도나 효율면에서 유리)
리스트 컴프리헨션
# [표현식 for 항목 in iterable객체]
In [47]: [i for i in range(1, 6)]
Out[47]: [1, 2, 3, 4, 5]
In [48]: [i*2 for i in range(1, 6)]
Out[48]: [2, 4, 6, 8, 10]
In [49]: [i for i in range(1, 15) if i % 2 == 0]
Out[49]: [2, 4, 6, 8, 10, 12, 14]
# 리스트 컴프리헨션의 중첩
# 3중 중첩까지 가면 알아보기 힘들기 때문에,
# 2중 중첩까지만 사용하는게 좋음
In [50]: [(color, fruit) for color in colors for fruit in fruits]
Out[50]:
[('red', 'apple'),
('red', 'banana'),
('red', 'melon'),
('yellow', 'apple'),
('yellow', 'banana'),
('yellow', 'melon'),
('green', 'apple'),
('green', 'banana'),
('green', 'melon'),
('purple', 'apple'),
('purple', 'banana'),
('purple', 'melon')]
셋 컴프리헨션
In [51]: {i for i in range(1,4)}
Out[51]: {1, 2, 3}
제네레이터 컴프리헨션
괄호로 되어있지만 튜플을 생성하지 않는다. 튜플은 컴프리헨션이 없다.
# 제너레이터 객체는 순회 가능하다.
In [51]: {i for i in range(1,4)}
Out[51]: {1, 2, 3}
In [52]: g = (item for item in range(10))
In [53]: g
Out[53]: <generator object <genexpr> at 0x10ac366c0>
In [54]: print(type(g))
<class 'generator'>
# 리스트 형태로 만들 수 있다.
In [55]: g_list = list(g)
In [56]: g_list
Out[56]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [57]: print(type(g_list))
<class 'list'>
실습
- for문을 2개 중첩하여 (0,0), (0,1), (0,2), (0,3), (1,0), (1,1)….. (6,3)까지 출력되는 반복문을 구현한다.
- 리스트 컴프리헨션을 중첩하여 위 결과를 똑같이 출력한다.
- 1, 2번의 반복문에서 튜플의 첫 번째 항목이 짝수일때만 출력하도록 조건을 변경한다.
- 1000에서 2000까지의 숫자 중, 홀수의 합을 구해본다.
- 리스트 컴프리헨션을 사용하여 구구단 결과를 갖는 리스트를 만들고, 해당 리스트를 for문을 사용해 구구단 형태로 나오도록 출력해본다. (각 단마다 한 번 더 줄바꿈을 넣어준다.)
- 1에서 99까지의 정수 중, 7의 배수이거나 9의 배수인 정수인 리스트를 생성한다. 단, 7의 배수이며 9의 배수인 수는 한 번만 추가되어야 한다.
In [1]: for i in range(7):
...: for j in range(4):
...: print('({}, {})'.format(i, j))
...:
In [2]: xy = [(x, y) for x in range(7) for y in range(4)]
In [4]: for i in xy:
...: print(i)
In [5]: for i in range(7):
...: if i % 2 != 0:
...: continue
...: for j in range(4):
...: print((i, j))
...:
# 이렇게 작성해도 되지만, 위의 코드가 더 효율적이다.
In [7]: for i in range(7):
...: for j in range(4):
...: if i % 2 == 0:
...: print((i, j))
...:
# 효율코드의 리스트 컴프리헨션
In [13]: [(i, j) for i in range(7) if i % 2 == 0 for j in range(4)]
In [16]: result = 0
In [17]: for i in range(1000, 2001):
...: if i % 2 != 0:
...: result += i
...:
In [18]: print(result)
750000
In [24]: result = [ x*y for x in range(2, 10) for y in range(2, 10)]
In [25]: index = 0
In [26]: for i in range(2, 10):
...: for j in range(2, 10):
...: print('{} x {} = {}'.format(i, j, result[index]))
...: index += 1
...: print('\n')
# enumerate : iterable 객체를 count
# 이용해 위에서 인덱스 역할을 편리하게 구현할 수 있다.
In [35]: for index, x in enumerate(range(1002, 1010)):
...: print('index: {}, value: {}'.format(index, x))
...:
index: 0, value: 1002
index: 1, value: 1003
index: 2, value: 1004
index: 3, value: 1005
index: 4, value: 1006
index: 5, value: 1007
index: 6, value: 1008
index: 7, value: 1009
# 다른 방법
In [32]: result = ['{} x {} = {}'.format(i, j, i*j) for i in range(2, 10
...: ) for j in range(1, 10)]
In [33]: for i in result:
...: print(i)
In [34]: for i in range(1, 100):
...: if i % 7 == 0 or i % 9 == 0:
...: print(i)
...:
In [35]: [i for i in range(1, 100) if i % 7 == 0 or i % 9 == 0]
함수
반복적인 작업을 하는 코드를 재사용이 가능하게 정의해 놓은 것
함수의 정의, 실행
# 함수 정의
In [1]: def func():
...: print('call func')
# 함수 자체는 function 객체를 참조하는 변수
In [2]: func
Out[2]: <function __main__.func>
In [4]: print(type(func))
<class 'function'>
# 함수 실행
In [5]: func()
call func
리턴 값이 있는 함수 정의
함수의 결과로 Bool값을 갖는 데이터를 리턴하여 if문이나 while문의 조건으로 사용가능하다.
In [6]: def return_true():
...: return True
...:
In [7]: return_true()
Out[7]: True
In [8]: result = return_true()
In [9]: print(result)
True
In [10]: print(type(result))
<class 'bool'>
In [11]: if return_true():
...: print('return_true')
...: else:
...: print('false')
...:
return_true
매개변수를 사용하는 함수 정의
In [12]: def print_arguments(something):
...: print(something)
...:
In [13]: print_arguments('ABC')
ABC
매개변수(parameter)와 인자(argument)의 차이
함수 내부에서 함수에게 전달되어 온 변수는 매개변수라 부르며, 함수를 호출할 때 전달하는 변수는 인자로 부른다.
# 함수 정의시, 매개변수
def func(매개변수1, 매개변수2):
# 함수 호출시, 인자
func(인자1, 인자2)
리턴값이 없을 경우
함수에서 리턴해 주는 값이 없을 경우, 아무것도 없다는 뜻을 가진 None
객체를 얻는다.
# 아무겂도 없다는 것을 알려주기위한 객체
In [16]: a = None
In [17]: print(type(a))
<class 'NoneType'>
# 파이썬이 미리 생성해논 객체이므로 똑같은 주소 참조
In [18]: id(a)
Out[18]: 4356116024
In [19]: b = None
In [20]: id(b)
Out[20]: 4356116024
위치 인자 (Positional arguments)
매개변수의 순서대로 인자를 전달하여 사용하는 경우
In [21]: def student(name, age, gender):
...: return {'name': name, 'age': age, 'gender': gender}
...:
In [24]: student('hmlim', 30, 'female')
Out[24]: {'age': 30, 'gender': 'female', 'name': 'hmlim'}
In [25]: student(30, 'hylee', 'male')
Out[25]: {'age': 'hylee', 'gender': 'male', 'name': 30}
In [26]: h_name = 'kdhong'
In [27]: h_age = 20
In [28]: h_gender = 'male'
In [29]: student(h_name, h_age, h_gender)
Out[29]: {'age': 20, 'gender': 'male', 'name': 'kdhong'}
키워드 인자 (Keyword arguments)
매개변수의 이름을 지정하여 인자로 전달하여 사용하는 경우이다. 순서 상관없이 인자를 전달한다. (예: 회원가입 받을 때)
In [31]: student(age=30, name='yhlee', gender='female')
Out[31]: {'age': 30, 'gender': 'female', 'name': 'yhlee'}
# 괄호안에서는 자유롭게 타이핑 가능
In [34]: student(
...: name = 'mike',
...: gender = 'male',
...: age = 35
...: )
Out[34]: {'age': 35, 'gender': 'male', 'name': 'mike'}
# 위치 인자와 키워드 인자를 혼합해 사용할 경우
In [35]: student('sam', 25, gender='male')
Out[35]: {'age': 25, 'gender': 'male', 'name': 'sam'}
# 키워드 인자는 맨 뒤에 전달
In [36]: student(name='kate', 40, 'female')
File "<ipython-input-36-0648f45f1b0d>", line 1
student(name='kate', 40, 'female')
^
SyntaxError: non-keyword arg after keyword arg
기본 매개변수값 지정
인자가 제공되지 않을 경우, 기본 매개변수로 사용할 값을 지정할 수 있다.
In [41]: def get_student(name, age, gender, school_class='WPS'):
...: return {'name': name, 'age': age, 'gender': gender, 'class': school_class}
...:
In [42]: get_student('hmlim', 30, 'female')
Out[42]: {'age': 30, 'class': 'WPS', 'gender': 'female', 'name': 'hmlim'}
In [43]: get_student('lhy', 30, 'male', 'WDS')
Out[43]: {'age': 30, 'class': 'WDS', 'gender': 'male', 'name': 'lhy'}
기본 매개변수값 정의 시점
기본 매개변수값은 함수가 실행될 때 마다 계산되지 않고, 함수가 정의 되는 시점에 계속해서 사용된다.
In [52]: def return_list1(value, result=[]):
...: result.append(value)
...: return result
# 인자가 제공되지 않을 경우,
# 기본 매개변수값으로 지정한 result=[] 사용
In [54]: return_list1('apple')
Out[54]: ['apple']
# 계속 사용
In [55]: return_list1('banana')
Out[55]: ['apple', 'banana']
# 인자가 제공된 경우,
# fruits_list 리스트 객체에 value 추가
In [56]: fruits_list = ['melon', 'orange']
In [57]: return_list1('lemon', fruits_list)
Out[57]: ['melon', 'orange', 'lemon']
In [60]: return_list1('mango')
Out[60]: ['apple', 'banana', 'mango']
In [61]: return_list1('apple', fruits_list)
Out[61]: ['melon', 'orange', 'lemon', 'apple']
In [58]: return_list1('peer', 'mango')
-------------------------------------------------------
AttributeError: 'str' object has no attribute 'append'
In [59]: return_list1('peer', f_list = ['mango'])
-------------------------------------------------------
TypeError: return_list1() got an unexpected keyword argument 'f_list'
함수가 실행되는 시점에 기본 매개변수 값을 계산하려면, 아래와 같이 바꿔준다.
# 기본 변수값을 None 객체로 지정
In [67]: def return_list2(value, result=None):
...: if result is None:
...: result = []
...: result.append(value)
...: return result
...:
# 이렇게 작성할 수 있지만,
# 사용하다 오류가 발생할 확률이 있으므로
# None을 사용하는게 좋다.
In [67]: def return_list2(value, result=3):
...: if result is 3:
...: result = []
...: result.append(value)
...: return result
...:
# 인자가 제공되지 않을 경우
In [68]: return_list2('apple')
Out[68]: ['apple']
In [69]: return_list2('banana')
Out[69]: ['banana']
# 인자가 제공된 경우,
# None 대신 주어진 인자값으로 대체
In [70]: return_list2('banana', fruits_list)
Out[70]: ['melon', 'orange', 'lemon', 'apple', 'banana']
In [72]: return_list1_step1 = return_list('red')
In [73]: return_list1_step2 = return_list('blue')
In [74]: id(return_list1_step1)
Out[74]: 4390107848
In [75]: id(return_list1_step2)
Out[75]: 4390107848
In [78]: return_list2_step1 = return_list2('red')
In [79]: return_list2_step2 = return_list2('blue')
In [80]: id(return_list2_step1)
Out[80]: 4389394760
In [81]: id(return_list2_step2)
Out[81]: 4390238024
# 사용예
In [20]: def add_value_for_list_or_return_new_list_contain_value(add_value, ori_list=None):
...: if ori_list is None:
...: ori_list = []
...: ori_list.append(add_value)
...: return ori_list
위치인자 묶음
함수에 위치인자로 주어진 변수들의 묶음은 *매개변수명
으로 사용할 수 있다. 관용적으로 *args
를 사용한다. 인자 개수가 정해지지 않았을 때 사용한다.
In [82]: def print_args(*args):
...: print(args)
...:
# 튜플로 반환
In [83]: print_args(1)
(1,)
In [84]: print_args(1, 2)
(1, 2)
In [85]: print_args(1, 2, 'abc', [])
(1, 2, 'abc', [])
In [86]: result = return_args(1, 2, 'abc', [])
# 키워드 인자는 사용할 수 없음
In [89]: result = return_args(1, 2, 'abc', [], k1='abc')
-------------------------------------------------------
TypeError: return_args() got an unexpected keyword argument 'k1'
키워드 인자 묶음
함수에 키워드인자로 주어진 변수들의 묶음은 **매개변수명
으로 사용할 수 있다. 관용적으로 **kwargs
를 사용한다.
In [11]: def print_kwargs(**kwargs):
...: print(kwargs)
...:
# 딕셔너리로 반환
In [12]: print_kwargs(name='hmlim', gender='female', age=30)
{'name': 'hmlim', 'age': 30, 'gender': 'female'}
In [15]: def all_args(*args, **kwargs):
...: print('position args: ', args)
...: print('keyword args: ', kwargs)
...:
# 키워드 인자는 맨 뒤에 전달
In [17]: all_args(123, 'abc', color='red')
position args: (123, 'abc')
keyword args: {'color': 'red'}
In [18]: all_args(color='blue', 124)
File "<ipython-input-18-fc7d069c059d>", line 1
all_args(color='blue', 124)
^
SyntaxError: non-keyword arg after keyword arg
# 사용예
In [29]: def print_args_len(*args):
...: print('args count: {}'.format(len(args)))
...:
In [30]: print_args_len(1, 2, 3, 4, 7)
args count: 5
In [31]: def print_kwargs_len(**kwargs):
...: print('kwargus count: {}'.format(len(kwargs)))
...:
In [33]: print_kwargs_len(name='abc')
kwargus count: 1
In [34]: def print_kwargs_key_value(**kwargs):
...: for item in kwargs.items():
...: print('key {}, value {}'.format(item[0], item[1]))
...:
In [35]: print_kwargs_key_value(name='hmlim', gender='female')
key name, value hmlim
key gender, value female
docstring
함수를 정의한 문서 역할을 한다. 함수 정의 후, 몸체의 시작부분에 문자열로 작성한다.
In [36]: def print_args_len(*args):
...: 'Print positional arguments with length'
...: print(args)
...: return len(args)
...:
# help 함수를 이용해 docstring을 볼 수 있다.
In [37]: help(print_args_len)
# 여러줄로 작성 가능
In [38]: def print_kwargs(**kwargs):
...: '''Print keyword arguments
...: and return length'''
...: print(kwargs)
...: return len(kwargs)
...:
In [39]: help(print_kwargs)
함수를 인자로 전달
파이썬에서 함수 역시 다른 객체와 동등하게 취급되므로 함수에서 인자로 함수를 전달, 실행, 리턴하는 형태의 프로그래밍이 가능하다.
In [40]: def print_call_func():
...: print('call func')
...:
In [42]: def excute_args_func(func):
...: func()
...:
In [43]: excute_args_func(print_call_func)
call func
내부함수
함수 안에서 또 다른 함수를 정의해 사용할 수 있다.
In [50]: def outer(val):
...: def inner():
...: return val.upper()
...: return inner()
...:
In [51]: outer('a')
Out[51]: 'A'