프로그래머가 하는일 - 추상화(abstraction)
절차 지향
procedure, procedural oriented
절치 지향보다는 프로시져 지향이라고 하는 것이 맞다.
객체 지향
- OOP(Object-Oriented Programming)
인터페이스(interface)와 구현(implementation)
interface
function signature
사용자들에게 제공(사용법만 알면 함수를 사용 가능하도록 함)
implementation
함수를 직접 만들기(내부 구현)
함수 이름은 기능을 명확하게 표현해야 함
매개 변수는 어떻게 설계하고 무엇을 인자로 받을 것인지 생각해야 함
결과 값으로 어떤 결과를 반환할 것인지 생각해야 함
1
2
3
4
5
6
7def func(a, b):
"""
func(integer, integer) -> integer
두 값을 인자로 받고
결과는 그 두 값을 더한 값
"""
return a + bctrl + ]를 사용하면 indent됨(범위를 지정하여 사용 가능)
함수 안에 “”” “”” 사이에 함수 설명을 넣을 수 있음
‘->’에는 반환되는 자료형을 써주는 것이 좋음
1
2
3
4
5
6
7help(func)
>> Help on function func in module __main__:
func(a, b)
func(integer, integer) -> integer
두 값을 인자로 받고
결과는 그 두 값을 더한 값사용자 입력 받기
1
2
3
4
5
6
7
8
9
10
11input_data = input("무엇이든 입력하세요 : ")
>> 무엇이든 입력하세요 : 여기에 입력
type(input_data)
>> str
data = int(input("숫자를 입력하세요 : ")) # int형변환
>> 숫자를 입력하세요 : 1
type(data)
>> int
Coding Practice
가위바위보 게임
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151def get_player_choice():
"""
get_player_choice() -> string
string : {'바위', '가위', '보'}
결과값이 위 세 값 중에 하나임을 보장한다.
"""
player = input("바위, 가위, 보 중에 한 가지를 입력하세요 : ")
while player != '바위' and player != '가위' and player != '보' :
player = input('다시 입력하세요 : ')
# while문에 직접 조건을 넣음
return player
import random
# 0 --> '바위'
# 1 --> '가위'
# 2 --> '보'
# random 내장 함수를 이용하기 위해 import로 random 모듈을 불러옴
# Tuple 이용
def get_computer_choice():
"""
get_computer_choice() -> string
string = {'바위', '가위', '보'}
"""
choice_tu = ('바위', '가위', '보')
computer = choice_tu[random.randint(0,2)]
# 정수형 랜덤 숫자를 받음
return computer
def who_wins(player, computer):
"""
who_wins(player, computer) -> string
string = {'player', 'computer', 'draw'}
"""
if player == '바위':
if computer == '바위':
winner = 'draw'
elif computer == '가위':
winner = 'player'
else:
winner = 'computer'
elif player == '가위':
if computer == '바위':
winner = 'computer'
elif computer == '가위':
winner = 'draw'
else:
winner = 'player'
else:
if computer == '바위':
winner = 'player'
elif computer == '가위':
winner = 'computer'
else:
winner = 'draw'
return winner
def play_one():
"""
play_one() -> string
string = {'player', 'computer', 'draw'}
한 판에 대해서
플레이어가 이기면 "플레이어 승" 출력
컴퓨터가 이기면 "컴퓨터 승" 출력
비기면 "무승부" 출력
무승부가 나면 둘 중에 한 명이 이길 때까지 반복
"""
while True:
player = get_player_choice()
computer = get_computer_choice()
winner = who_wins(player, computer)
if winner == 'player':
print('플레이어 승!')
return 'player'
elif winner == 'computer':
print('컴퓨터 승!')
return 'computer'
else:
print('무승부')
pass
# pass는 실행할 것이 아무것도 없다는 의미
# pass는 아무런 동작을 하지 않고 다음 코드를 실행
# continue는 다음 순번의 loop를 실행
# pass와 continue의 차이 알기
def play():
while True:
try:
user_num_games = int(input("1: 3판2선승, 2: 5판3선승: "))
if user_num_games != 1 and user_num_games != 2:
print("1 또는 2의 값만 입력하세요.")
continue
else:
break
except ValueError:
print("숫자가 아닌 값을 입력하셨습니다. 다시 입력하세요.")
#user_num_games --> 1 or 2
num_games = 3 if user_num_games == 1 else 5
#3판 2선승 --> 2승 or 5판 3선승 --> 3승
count = 2 if num_games == 3 else 3
win_list = []
# 리스트를 만들어서 이긴 대상을 리스트 인덱스로 넣어둔다.
# 리스트 내장 함수 count를 사용하여 선승을 판단한다.
# for문 내부에 i라는 변수를 사용하지 않으면 _로 표시해도 무관하다.
for _ in range(num_games):
win_list.append(play_one())
print('player : ', win_list.count('player'),'승', 'computer : ', win_list.count('computer'),'승')
if win_list.count('player') >= count:
print("플레이어 우승!")
break
elif win_list.count('computer') >= count:
print("컴퓨터 우승!")
break
play()
>> 1: 3판2선승, 2: 5판3선승: 1
바위, 가위, 보 중에 한 가지를 입력하세요 : 바위
무승부
바위, 가위, 보 중에 한 가지를 입력하세요 : 가위
컴퓨터 승!
player : 0 승 computer : 1 승
바위, 가위, 보 중에 한 가지를 입력하세요 : 보
컴퓨터 승!
player : 0 승 computer : 2 승
컴퓨터 우승!
pass와 continue
pass
실행할 코드가 없다는 것을 의미
다음 코드를 실행
1
2
3
4
5for i in range(1, 5):
if i == 3:
pass
print(i, end = ' ') # 3일 때에도 print 함수를 실행함
>> 1 2 3 4
continue
조건이 참이 되면 다음 순번으로 강제 이동
1
2
3
4
5for i in range(1, 5):
if i == 3:
continue
print(i, end = ' ') # 3일 때 loop의 다음 순번으로 이동, print 함수를 실행하지 않음
>> 1 2 4
packing과 unpacking
packing
tuple로 선언하지 않았음
type은 tuple로 나옴 = packing이 되었음
1
2
3container = 1, 2, 3, 4, 5
type(container)
>> tuple
unpacking
위 container 변수를 unpacking 함
변수 앞에 *를 붙여주면 묶음
1
2
3
4
5
6
7
8
9a, b, *c = container
a
>> 1
b
>> 2
c
>> [3, 4, 5]dictionary에서 items()도 unpacking
1
2
3
4dic = {'a' : 1, 'b' : 2}
for k, v in dic.items():
print(k,v, end = ' ')
>> a 1 b 2
packing과 unpacking 활용
함수에서 매개변수 앞에 *를 붙여주면 가변인자로 받을 수 있다.
1
2
3
4
5def sum_int(*args): # 함수에서 가변인자 받는 방법
s = 0
for arg in args:
s += arg
return s아래와 같이 1, 2, 3, 4, 5의 가변인자가 들어오면 tuple로 packing이 됨
1
2sum_int(1, 2, 3, 4, 5)
>> 15아래와 같이 list 형태로 가변인자를 넣게 되면 하나의 데이터로 인식하여 에러 발생
1
2
3
4li = [1, 2, 3, 4]
sum_int(li)
>> TypeError: unsupported operand type(s) for +=: 'int' and 'list'따라서 *를 붙여서 다시 unpacking하여 사용
1
2
3# *를 붙여서 다시 unpacking하여 사용
sum_int(*li)
>> 10아래와 같은 매개변수의 형태로 모든 인자를 다 받을 수 있다.
args : non keyword arguments
kwargs : keyword arguments
kwargs는 dictionary를 packing할 때 사용한다.(keyword가 존재)
함수를 정의할 때, *args, **kwargs는 가변인자를 받겠다는 의미이다.
1
2
3
4
5
6
7def sum_int(*args, **kwargs):
print(args)
print(kwargs)
sum_int(1, 2, 3, age = 100, weight = 100)
>> (1, 2, 3)
{'age': 100, 'weight': 100}keyword가 없는 인자는 앞에, keyword가 있는 인자는 뒤에 위치해야 한다.
keyword 인자 뒤에 keyword가 없는 인자가 존재하면 에러가 발생한다.
1
2sum_int(1, 2, 3, age = 100, weight = 100, 4)
>> SyntaxError: positional argument follows keyword argument함수를 호출하는 입장에서의 *, **는 unpacking을 의미한다.
1
2
3sum_int(*li, **dic)
>> (1, 2, 3, 4)
{'a': 1, 'b': 2}
삼항 연산자
‘참인 경우의 값’ if ‘조건’ else ‘거짓인 경우의 값’
if문의 일반 사용 예
1
2
3
4
5
6a = 10
if a >= 10:
print('good!')
else:
print('bad!')
>> good!삼항 연산자 적용 예
1
2
3
4
5# if 조건문 결과는 앞에, else 조건문 결과는 뒤에 위치시킨다.
# if else 간에 ':'를 붙이지 않아도 된다.
print('good!') if a >= 10 else print('bad!')
>> good!
재귀 함수(recursive function, recursion)
자기가 자기 자신을 호출하는 함수
기저 조건(base case) = 종료 조건, 탈출 조건
Basic
기저 조건을 반드시 정해줘야 한다.(종료, 탈출)
재귀하는 과정에서 자기 자신을 만날 때마다 blocking이 걸린다.
blocking이 걸린 다음에 함수가 호출되며 stack frame에 쌓인다.
함수가 쌓일 수 있는 stack frame 공간이 정해져 있다.
정해진 stack frame을 넘어버리면 stack overflow가 발생한다.
1
2
3
4
5
6
7
8
9
10
11
12def func(num):
# 기저 조건(base case)
# 종료 조건
# 탈출 조건
if num <= 0:
return
print(num, end = ' ')
func(num - 1)
func(5)
>> 5 4 3 2 1
Basic function example
factorial(계승)
점화식 –> fac(num) = fac(num - 1)*num
기저 조건 –> if num == 1 return 1
1
2
3
4
5
6
7
8
9def factorial(num):
if num == 1:
return 1
return factorial(num - 1) * num
for num in range(1, 10):
print(factorial(num), end = ' ')
>> 1 2 6 24 120 720 5040 40320 362880
fibonacci(피보나치)
점화식 : fibo(n) = fibo(n - 2) + fibo(n - 1)
기저 조건 : if n == 1 or n == 2 then return 1
1
2
3
4
5
6
7
8
9def fibonacci(n):
if n == 1 or n == 2:
return 1
return fibonacci(n - 2) + fibonacci(n - 1)
for n in range(1, 10):
print(fibonacci(n), end = ' ')
>> 1 1 2 3 5 8 13 21 34