In [2]:
from __future__ import print_function

In [1]:
def hello_world():
    msg = 'hello, world!'
    return msg

greeting = hello_world()
print(greeting)


hello, world!

인자의 기본값


In [60]:
def greetings(hour, lang='kr', extra_msg=None):
    # 시간값 확인
    if hour < 0 or hour > 24:
        return
    
    # 언어에 따라 메시지 설정
    msgs = {'kr': [u'좋은', u'아침', u'오후', u'저녁', u'밤'],
            'en': [u'Good', u'morning', u'afternoon', u'evening', 
                   u'night']}

    # 별도로 설정된 메시지가 있으면, 해당 메시지 반영
    if not extra_msg is None:
        for key, value in extra_msg.items():
            msgs[key] = value
    
    # 해당 언어가 없으면 함수 종료
    if not lang in msgs:
        return
    
    msg_prefix = msgs[lang][0]
    
    # 시간에 따른 메시지 설정
    msg = msg_prefix + ' '
    if 6 < hour < 12:
        msg += msgs[lang][1]
    elif 12<= hour < 18:
        msg += msgs[lang][2]
    elif 18<= hour < 21:
        msg += msgs[lang][3]
    else:
        msg += msgs[lang][4]
    return msg

print(greetings(9, lang='fr', 
                extra_msg={'fr': 
                           ['bon', 
                            'jour', 'soir', 'nuit']}))
print(greetings(13))
print(greetings(19))
print(greetings(22))
print(greetings(-2))


bon jour
좋은 오후
좋은 저녁
좋은 밤
None

In [10]:
# return의 효과
def many_exits(exit_no):
    if exit_no==1:
        return 'Exit 1'
    if exit_no==2:
        return 'Exit 2'
    if exit_no==3:
        return 'Exit 3'
    
    return '그런 출구는 없습니다.'

print(many_exits(1))
print(many_exits(2))
print(many_exits(9))


Exit 1
Exit 2
그런 출구는 없습니다.

함수 인자

함수의 인자를 학습하는 예시


In [29]:
def juicer(ingredient, customer_name):
    result = customer_name + u' 님, '

    # TODO: 가능한 메뉴인지 확인
    menu = [u'딸기', u'사과', u'망고']
    if not ingredient in menu:
        return None
    
    result += ingredient + u' 주스'
    if ingredient == u'딸기':
        price = 10
    elif ingredient == u'사과':
        price = 15
    elif ingredient == u'망고':
        price = 20
   
    return result, price

In [30]:
result = juicer(u'딸기', u'성주')
if result is None:
    print('그런 메뉴 없습니다.')
else:
    msg, price = result # 결과 튜플 언패킹
    print(msg + u' 나왔습니다.')
    print('가격: ' + str(price))
# 출력 예시: 성주 님, 딸기 주스 나왔습니다.
# 딸기 주스는 10원입니다.
# 사과 주스는 15원입니다.
# 망고 주스는 20원입니다.


성주 님, 딸기 주스 나왔습니다.
가격: 10

두 개 이상의 결과 반환(return)


In [9]:
def swap(x,y):
    return (y,x)

print(swap(1,2))


(2, 1)

In [4]:
# 함수 정의
def foo(a,b):
    return a*2, b*2

# 함수 호출
aa, bb = foo(1,2)
print(aa,bb)

result = foo(1,2)
print(type(result))
print(result[0], result[1])


2 4
<type 'tuple'>
2 4

인자에 미치는 효과


In [74]:
def double(x):
    x = x*2
    
x = 1
double(x)
print(x)


1

In [80]:
def square_not_safe(seq):
    for i, n in enumerate(seq):
        seq[i] = seq[i]**2

def square_safe(seq):
    # 값 복사
    seq = list(seq[:])
    for i, n in enumerate(seq):
        seq[i] = seq[i]**2
        
    return seq

nums = [1,2,3,4]
result = square_safe(nums)
print(nums)
print(result)

# list --> tuple
nums = tuple(nums)
square_not_safe(nums)


[1, 2, 3, 4]
[1, 4, 9, 16]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-80-8af4119b208f> in <module>()
     18 # list --> tuple
     19 nums = tuple(nums)
---> 20 square_not_safe(nums)

<ipython-input-80-8af4119b208f> in square_not_safe(seq)
      1 def square_not_safe(seq):
      2     for i, n in enumerate(seq):
----> 3         seq[i] = seq[i]**2
      4 
      5 def square_safe(seq):

TypeError: 'tuple' object does not support item assignment

함수의 스코프에서 선언된 변수는 지역변수


In [91]:
def func(x):
    y = x
    
func(1)
print(y)


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-91-476778a57994> in <module>()
      3 
      4 func(1)
----> 5 print(y)

NameError: name 'y' is not defined

제네레이터 (Generator)


In [31]:
def countdown(n):
    print('카운트 다운 시작!')
    while n>0:
        yield n
        n -=1

In [32]:
c = countdown(10)

In [33]:
c.next()


카운트 다운 시작!
Out[33]:
10

In [34]:
c.next()


Out[34]:
9

In [35]:
for c in countdown(10):
    print(c, end=' ')


카운트 다운 시작!
10 9 8 7 6 5 4 3 2 1 

도전과제

리스트, 문자열과 같은 시퀀스를 받아서 홀수번째 원소만 선택해 반환하는 함수 its_odd를 정의하시오.

예:

result = its_odd(u'파이썬')
print(result) # '파썬'

result = its_odd([1,2,3,4,5])
print(result) # [1,3,5]

a. 입력과 출력을 다음 형식으로 파일 its_odd_result.txt에 저장하시오.

파이썬 --> 파썬

[1,2,3,4,5] --> [1,3,5]


In [81]:
def its_odd(seq):
    result = seq[::2]
    return result

result = its_odd(u'파이썬')
print(result)

print(its_odd([1,2,3,4,5]))


파썬
[1, 3, 5]

In [88]:
type(its_odd)


Out[88]:
function

In [89]:
its_odd(range(10))


Out[89]:
[0, 2, 4, 6, 8]

In [90]:
xx = its_odd
xx(range(10))


Out[90]:
[0, 2, 4, 6, 8]

In [94]:
def save_to_file(func, input_seq, filename, str_format=u'{} --> {}'):
    output_seq = func(input_seq)
    f = open(filename, 'w')
    # TODO: 문자열 인코딩 수행
    text_encoded = str_format.format(input_seq, output_seq).encode('utf-8')
    f.write(text_encoded)
    f.close()

In [86]:
save_to_file(its_odd, [1,2,3,4,5], 'its_odd_result.txt')

In [92]:
def its_even(seq):
    return seq[1::2]

save_to_file(its_even, [1,2,3,4,5], 'its_even_result.txt')

그런데, 유니코드 저장을 하려고 하니까 ... ?


In [95]:
save_to_file(its_odd, u'파이썬', 'its_odd_result.txt')

도전과제

피보나치 수열은 다음과 같다.

0 1 1 2 3 5 8 ...

a. 임의의 n개의 피보나치 수열을 리스트로 반환하는 함수 generate_fibo를 작성하시오.

b. generate_fibo 호출 시, 시작 숫자 두 개를 지정할 수 있도록 하시오. 인자를 설정하지 않으면 수열은 0,1로 시작한다. 생성 개수를 지정하지 않으면, 기본적으로 10개의 숫자를 생성하도록 만드시오.


In [63]:
def generate_fibo(a=0,b=1,n=10):
    fibos = [a,b]
    # 지정된 개수만큼 원소 추가
    while len(fibos)<n:
        # 새 원소 생성 후 a, b 값 교체
        a,b = (b, a+b)
        # 새로 생성된 값을 결과에 추가
        fibos.append(b)
    
    return fibos

generate_fibo()


Out[63]:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

도전과제

포커 카드 52장을 게임 참가자에게 각각 5장씩 나눠주는 프로그램을 작성하시오. 포커 카드는 참가자에게 나눠주기 전에 무작위로 섞여야 한다. 참가자의 수는 2-4명이 될 수 있다.

a. 포커 카드를 나눠주고 나서 각 참가자가 받은 포커 카드를 모두 출력한다.

예:

이성주 : H2, D2, SJ, C10, S3

김성주 : C3, D4, CK, SK, H9

b. 각 참자자의 카드의 숫자를 기준으로 오름차순으로 정렬해 출력한다.


In [3]:
from __future__ import print_function
import random

# 1. 카드덱 생성
def generate_card():
    # 52장 카드 덱 생성
    suits = ['Heart', 'Diamond', 'Clover', 'Spade']
    ranks = range(2,11)+['J', 'Q', 'K', 'A']
    deck = []
    for s in suits:
        for r in ranks:
            card = s + str(r)
            deck.append(card)
    return deck

# 2. 카드덱 나눠주기
def play_card_game(deck, players):
    # 나눠주기 전에 섞어야지
    random.shuffle(deck)
    
    # 인제 나눠줘야지 ...
    for person in players:
        person['hand'] = deck[:5]
        deck = deck[5:]
        
    return

In [72]:
deck = generate_card()
players = [{'name':'이성주'}, {'name':'김성주'}]
play_card_game(deck, players)

print(len(deck))

for person in players:
    print(person['name'], end=': ')
    print(person['hand'])


52
이성주: ['Spade3', 'SpadeA', 'Heart5', 'Spade5', 'DiamondJ']
김성주: ['Diamond10', 'SpadeQ', 'Heart8', 'Diamond6', 'Heart9']

도전과제

52장의 포커 카드가 있다. 이 카드를 사용해 블랙잭 게임을 한다.

블랙잭 게임은 각 참가자가 처음에 두 장의 카드를 받는다. 각 카드의 숫자를 모두 더 해 21인지 확인한다.

  • 21이면 블랙잭! 게임이 종료되고 승리한다.
  • 숫자의 합이 21보다 작으면 한 장의 카드를 더 받는다.
  • 숫자의 합이 21보다 크면 게임에서 패배한다.

a. 받은 카드패를 파일로 출력해 저장한다.

참가자: 이성주

2015-07-08

HJ, HK 패!

HJ, S10 블랙잭!


In [22]:
from __future__ import print_function
import random

# 52장의 카드덱 생성
def gen_deck():
    ranks = list(range(2,11))+['J', 'Q', 'K', 'A']
    suits = ['Spade', 'Heart', 'Diamond', 'Clover']
    
    deck = [] # 카드덱 초기화
    for s in suits:
        for r in ranks:
            deck.append((s, r))
            
    # 잘 섞기
    random.shuffle(deck)
    return deck

def get_card_value(hand):
    """카드패의 숫자값 합계"""
    # 현재 hand의 카드의 숫자를 모두 더한다.
    value=0
    for card in hand:
        # 현재 카드의 숫자값
        rank = card[1]
        if rank=='A':
            value = value + 14
        elif rank=='K':
            value = value + 13
        elif rank == 'Q':
            value = value + 12
        elif rank == 'J':
            value = value + 11
        else:
            # 숫자인 경우는 그냥 더해준다.
            value = value + rank
                
    return value

def play_blackjack(player, output_file=None):
    # 블랙잭 게임 시작
    deck=gen_deck()

    # 카드 두 장 받기
    player['hand'] = [deck.pop(), deck.pop()]

    while True:
        play_log = u'카드패: {}'.format(player['hand'])
        play_log += u'\n'

        # 카드패 숫자값 합계
        hand_value = get_card_value(player['hand'])

        play_log += u'카드 숫자값= {}'.format(hand_value)
        play_log += u'\n'
        if hand_value == 21:
            play_log += u'블랙잭!!!!!!!' 
            play_log += u'\n'
            print(play_log)
            break
        elif hand_value > 21:
            play_log += u'돈 잃었다...'
            play_log += '\n'
            print(play_log)
            break
        elif hand_value < 21:
            # 카드를 한 장 더 받는다.
            player['hand'].append(deck.pop())
            play_log += u'인생을 계속 살아봐야 아는 거지 ... 한 장 더'
            play_log += u'\n'
            print(play_log)
            
    # 게임 결과를 파일로 출력
    if output_file is not None:
        f = open(output_file, 'a')
        text_encoded = play_log.encode('utf-8')
        f.write(text_encoded)
        f.close()
            
play_blackjack({'name':u'이성주'}, output_file='blackjack_log.txt')


카드패: [('Diamond', 'K'), ('Clover', 6)]
카드 숫자값= 19
인생을 계속 살아봐야 아는 거지 ... 한 장 더

카드패: [('Diamond', 'K'), ('Clover', 6), ('Clover', 2)]
카드 숫자값= 21
블랙잭!!!!!!!


In [6]:
deck = gen_deck()
hand = deck[:3]
print(hand)
get_card_value(hand)


[('Spade', 10), ('Clover', 2), ('Spade', 5)]
Out[6]:
17

도전과제

5개의 임의의 카드패 100개 정보를 담은 파일을 생성한다. 이 파일의 각 카드패에 포커 (같은 숫자 4개)가 있는지 확인하는 프로그램을 작성한다.


In [27]:
# list의 원소를 문자열로 반환하는 구문
text = ''
for c in ['a','b','c']:
    text += c
print(text)


abc

In [45]:
# sequence 형의 원소를 문자열로 반환
# 파이썬 표준 라이브러리 활용
import string
text = string.join(('Spade', str(6)), sep=' ')
print(text)


Spade 6

In [33]:
# 문자열을 list로 변환
'a,b,c'.split(',')


Out[33]:
['a', 'b', 'c']

In [89]:
import string

def card_to_string(card):
    return string.join((str(card[0]), str(card[1])), sep=' ')

def gen_hands(filename = 'hand_100.txt', n=100):
    # 카드패 파일 생성
    f = open(filename, 'w')
    for i in range(n):
        hand = gen_deck()[:5]
        # 카드패 정보를 문자열로 변환
        for card in hand:
            card_str = card_to_string(card)
            f.write(card_str)
            f.write(',')
        f.write('\n')
    
    f.close()

In [78]:
from __future__ import print_function

def is_pocker(hand):
    """카드패가 포커(4장의 같은 숫자 포함)인지 확인"""
    # TODO: 포커 탐지
    """
    X O O O O
    O X O O O
    O O X O O
    O O O X O
    O O O O X
    """
    # 카드패에서 숫자만 추출
    ranks = []
    for card in hand:
        ranks.append(str(card[1]))

    #print(ranks) # 디버깅용 출력
    
    # 자료 구조를 바꾸는 방법
    # 더 좋은 방법을 찾아야 할 듯 ...
    if len(set(ranks)) == 2:
        return True
    
    return False

def to_list(hand_str_list):
    hand_list = []
    for l in hand_str_list:
        # 카드패를 list로 변환
        hand_str = l.split(',')[:-1]
        # 카드패의 각 원소를 튜플로 변환
        hand = []
        for card in hand_str:
            hand.append(tuple(card.split()))
        hand_list.append(hand)
    return hand_list

def check_pockers(filename):
    """파일을 읽어들여, 카드패에서 포커 패턴 탐지"""
    f = open(filename)
    hand_list = to_list(f.readlines())
    f.close() # 파일 읽기 종료
    
    # 각 패의 포커 탐지
    for hand in hand_list:
        if is_pocker(hand):
            print(hand, end=': ')
            print('포커!')

In [80]:
is_pocker([('H',7), ('D',7), ('S',7), ('D',2), ('C',7)])


Out[80]:
True

In [90]:
filename = 'hand_10000.txt'
gen_hands(filename, n=10000)
check_pockers(filename)


[('Diamond', 'K'), ('Diamond', 'J'), ('Clover', 'J'), ('Heart', 'K'), ('Clover', 'K')]: 포커!
[('Clover', '2'), ('Heart', '2'), ('Spade', '2'), ('Spade', '9'), ('Heart', '9')]: 포커!
[('Diamond', '5'), ('Spade', '5'), ('Spade', '3'), ('Clover', '3'), ('Clover', '5')]: 포커!
[('Clover', '8'), ('Spade', '6'), ('Heart', '6'), ('Clover', '6'), ('Diamond', '8')]: 포커!
[('Spade', '6'), ('Spade', 'Q'), ('Diamond', 'Q'), ('Heart', '6'), ('Clover', '6')]: 포커!
[('Clover', '3'), ('Clover', '4'), ('Heart', '4'), ('Heart', '3'), ('Spade', '3')]: 포커!
[('Heart', 'A'), ('Heart', '9'), ('Clover', 'A'), ('Diamond', 'A'), ('Spade', 'A')]: 포커!
[('Heart', '7'), ('Diamond', '9'), ('Spade', '9'), ('Diamond', '7'), ('Clover', '7')]: 포커!
[('Spade', 'K'), ('Clover', 'K'), ('Diamond', '3'), ('Clover', '3'), ('Heart', '3')]: 포커!
[('Spade', 'Q'), ('Spade', 'K'), ('Heart', 'Q'), ('Clover', 'Q'), ('Diamond', 'Q')]: 포커!
[('Spade', '7'), ('Heart', '7'), ('Clover', '7'), ('Clover', '5'), ('Heart', '5')]: 포커!
[('Clover', '3'), ('Clover', '8'), ('Diamond', '3'), ('Spade', '8'), ('Heart', '3')]: 포커!
[('Clover', '4'), ('Spade', '6'), ('Heart', '4'), ('Heart', '6'), ('Clover', '6')]: 포커!
[('Spade', '6'), ('Heart', '6'), ('Spade', '2'), ('Heart', '2'), ('Diamond', '6')]: 포커!
[('Heart', 'A'), ('Clover', '5'), ('Spade', '5'), ('Clover', 'A'), ('Heart', '5')]: 포커!
[('Heart', 'Q'), ('Diamond', 'Q'), ('Heart', '4'), ('Spade', 'Q'), ('Diamond', '4')]: 포커!
[('Heart', '7'), ('Heart', 'Q'), ('Diamond', '7'), ('Clover', '7'), ('Spade', 'Q')]: 포커!
[('Clover', '8'), ('Spade', '8'), ('Heart', '8'), ('Heart', '9'), ('Clover', '9')]: 포커!
[('Clover', '7'), ('Spade', '6'), ('Clover', '6'), ('Diamond', '6'), ('Heart', '7')]: 포커!
[('Diamond', '6'), ('Diamond', '5'), ('Heart', '5'), ('Spade', '6'), ('Heart', '6')]: 포커!
[('Spade', 'J'), ('Clover', '9'), ('Diamond', '9'), ('Heart', '9'), ('Spade', '9')]: 포커!
[('Diamond', 'J'), ('Diamond', '4'), ('Heart', '4'), ('Spade', '4'), ('Spade', 'J')]: 포커!
[('Spade', '7'), ('Spade', '8'), ('Clover', '8'), ('Heart', '8'), ('Diamond', '7')]: 포커!

도전과제

카드의 모음을 패(hand)라고 한다. 카드패에서 다음의 경우를 판정하는 프로그램을 작성한다.

  1. 같은 숫자 네 개가 있는 경우
  2. 숫자 다섯 개가 연속되는 경우
  3. 같은 문양이 다섯 개인 경우
  4. 같은 숫자 쌍이 있는 경우

In [ ]: