코드잇 Codeit/Python / ML / DL

[코드잇] 파이썬 프로그래밍 기초 - 파이썬 응용하기

꼽파 2023. 8. 4. 18:47


  • 1. 파이썬 모듈 맛보기

  • 2. 사용자 입력 받기

  • 3. 파일 읽고 쓰기

  • 4. 프로젝트: 로또 시뮬레이션

  • 5. 프로젝트: 숫자 야구

  • 1. 파이썬 모듈 맛보기

    모듈

    같은 폴더에 있는 파이썬 파일만 불러올 수 있음.

    run.py와 calculator.py랑 같은 폴더에 있기 때문에 불러올 수 있음.

    다른 폴더에 있는 파일을 불러오는 것은 다음 토픽에 나옴.

     

    import calculator
    # 같은 폴더 내에 있는 calculator 파일을 불러오기
    # calculator.py 파일 = 모듈
    # 다른 파이썬 프로그램에서 사용할 수 있는 파이썬 코드 = 모듈
    
    print(calculator.add(2, 5))  # 7
    print(calculator.multiply(3, 4))  # 12 
    
    
    ###
    불러오는 모듈 이름을 지정
    ###
    
    import calculator as calc
    # as calc = 모듈 사용 시 calculator 대신 calc를 쓰겠다는 말
    # calculator 파일을 불러옴
    
    print(calc.add(2, 5))  # 7
    print(calc.multiply(3, 4))  # 12 
    
    
    ###
    특정 모듈에서 필요한 함수만 불러오기
    ###
    
    from calculator import add, multiply
    # calculator에서 특정 함수(add, multiply)만 불러오기
    
    print(add(2, 5))  # 7
    print(multiply(3, 4))  # 12 
    
    # 앞에 모듈 이름 안 붙여도 됨.
    # add, multiply 함수는 마치 파일 내에서 정의한 함수인 것처럼 사용할 수 있음.
    
    
    ###
    특정 모듈에서 모든 함수 불러와서 사용하기
    ###
    
    from calculator import *  
    # 모든 함수를 불러오라는 뜻 
    
    print(add(2, 5))  # 7
    print(multiply(3, 4))  # 12
    
    # 함수들의 출처가 불분명해서 권장하지 않음.
    # 필요한 함수만 불러오거나 import calculator as calc 방식 추천

     

    스탠다드 라이브러리

    # standard library (표준 라이브러리)
    
    import math  # 수학 관련 기능을 모아둔 모듈
    
    print(math.log10(100))  # 2.0
    print(math.cos(0))  # 1.0
    print(math.pi)  # 3.141592653589793

    import random
    
    print(random.random())
    # 0~1 사이 중 랜덤의 수가 출력
    # 0.7612105763848416

     

    random 모듈

    import random
    
    """
    randint() 함수
    
    randint(a, b)
    a ≤ N ≤ b를 만족하는 어떤 랜덤한 정수 N을 리턴
    """
    
    print(random.randint(1, 20))  # 12
    print(random.randint(5, 100))  # 68
    
    """
    uniform() 함수
    uniform(a, b)
    a ≤ N ≤ b를 만족하는 어떤 랜덤한 소수 N을 리턴
    """
    
    print(random.uniform(0, 1))  # 0.9688231124898523
    print(random.uniform(0, 1))  # 0.6065646256435557

     

    datetime 모듈

    import datetime
    
    """
    datetime 값 생성
    """
    
    # 2023년 3월 14일 
    
    pi_day = datetime.datetime(2023, 3, 14)
    print(pi_day)  # 2023-03-14 00:00:00
    print(type(pi_day))  # <class 'datetime.datetime'>
    
    # 시각은 자동으로 00시 00분 00초로 설정되어 있음.
    # 시각을 임의로 변경 가능
    
    pi_day = datetime.datetime(2023, 3, 14, 15, 16, 15)
    print(pi_day)  # 2023-03-14 15:16:15
    print(type(pi_day))  # <class 'datetime.datetime'>
    
    """
    오늘 날짜
    
    코드를 실행한 지금 이 순간의 날짜 불러오기기
    """
    
    today = datetime.datetime.now()
    print(today)  # 2023-08-01 06:18:54.881155
    print(type(today))  # <class 'datetime.datetime'>
    import datetime
    
    """
    timedelta 타입
    """
    """
    두 datetime 값 사이의 기간
    숫자 뺄셈으로 연산하기
    """
    
    today = datetime.datetime.now()
    pi_day = datetime.datetime(2023, 3, 14, 13, 6, 15)
    print(today - pi_day)  # 139 days, 17:24:45.524085
    print(type(today - pi_day))  # <class 'datetime.timedelta'>
    
    
    """
    timedelta 생성해서 datetime 값에 더하기기
    """
    today = datetime.datetime.now()
    my_timedelta = datetime.timedelta(days = 5, hours = 3, minutes = 10, seconds = 50)
    
    print(today)  # 2023-08-01 06:33:27.952853
    print(today + my_timedelta)  # 2023-08-06 09:44:17.952853
    
    
    """
    datetime에서 여러가지 값 추출
    """
    today = datetime.datetime.now()
    
    print(today)  # 2023-08-01 06:35:29.810582
    print(today.year)  # 2023
    print(today.month)  # 8
    print(today.day)  # 1
    print(today.hour)  # 6
    print(today.minute)  # 35
    print(today.second)  # 29
    print(today.microsecond)  # 810582
    
    
    """
    strftime() 함수
    
    datetime 포매팅
    """
    
    today = datetime.datetime.now()
    
    print(today)
    print(today.strftime("%A, %B %dth %Y"))  # 2023-08-01 06:37:19.722723 Tuesday, August 01th 2023
    
    # %a, %m 같은 걸 포맷코드라고 함

    2. 사용자 입력 받기

    input

    number = int(input("숫자를 입력하세요: "))
    print(number + 5)
    
    # input으로 들어온 값은 문자임
    # 문자와 정수를 더하면 오류가 남
    
    
    number = int(input("숫자를 입력하세요: "))
    print(number + 5)
    
    # input값을 int 정수로 형변환해주기

     

    숫자 맞히기 게임

    1부터 20까지 수 중 랜덤으로 생성하여 총 4번의 기회 동안 사용자가 맞히는 게임

    import random
    
    count = 4  # 남은 기회가 총 4번
    ans_num = random.randint(1, 20)  # 1부터 20까지 정수를 랜덤으로 생성
    
    while count >= 1:
        rand_num = int(input("기회가 {}번 남았습니다. 1-20 사이의 숫자를 맞혀 보세요:".format(count)))  
        # count가 줄어들 때마다 입력을 새로 받아야 함 -> while문 안으로 input함수를 넣어야 함
        if ans_num > rand_num:
            print("up")
        elif ans_num < rand_num:
            print("down")
        else:
            print("축하합니다. {}번 만에 숫자를 맞히셨습니다.".format(4-count))
            break
        
        count -= 1
        # 어떤 결과가 나오든 남은기회(count)가 하나씩 줄어들도록 해야 함.
    
    if count == 0:
        print("아쉽습니다. 정답은 {}입니다.".format(ans_num))
    import random
    
    # 상수 정의
    ANSWER = random.randint(1, 20)
    NUM_TRIES = 4
    
    # 변수 정의
    guess = -1
    tries = 0
    
    while guess != ANSWER and tries < NUM_TRIES:
        guess = int(input("기회가 {}번 남았습니다. 1-20 사이의 숫자를 맞혀 보세요: ".format(NUM_TRIES - tries)))
        tries += 1    
        
        if ANSWER > guess:
            print("Up")
        elif ANSWER < guess:
            print("Down")
    
    if guess == ANSWER:
        print("축하합니다. {}번 만에 숫자를 맞히셨습니다.".format(tries))
    else:
        print("아쉽습니다. 정답은 {}입니다.".format(ANSWER))

    3. 파일 읽고 쓰기

    파일 읽기

    매출 txt는 GPT한테 만들어달라고 하자

    with open('chicken.txt', 'r') as f:
    
    """
    open(파일이름, 문자열 r)
    r = read (읽기) / w = write (쓰기)
    현재 chicken.txt 파일이 같은 폴더 안에 있어서 경로를 별도로 작성 안 함.
    읽어드린 파일은 'f'라는 변수에 저장함.
    """
    
    with open('data/chicken.txt', 'r') as f:
    
    """
    현재 chicken.txt 파일이 data 폴더 안에 있음.
    """
    
    with open('data/chicken.txt', 'r') as f:
        print(type(f))
        # <class '_io.TextIOWrapper'>

    with open('data/chicken.txt', 'r', encoding='utf-8') as f:
        for line in f:
            print(line)
    
    # 한 줄씩 순서대로 변수 line에 지정됨
    # 마지막 줄까지 돌면 for 반복문이 끝남

     

    strip

    print("Hello")
    print("Hello")
    
    """
    Hello
    Hello
    """
    
    print("Hello\n")
    print("Hello")
    
    """
    Hello
    
    Hello
    """
    
    # print문은 기본적으로 엔터가 반영(개행된 상태)
    # ''\n'을 붙이면 한 줄이 띄어짐
    """
    strip
    문자열의 앞 뒤에 있는 화이트스페이스를 없애줌
    화이트스페이스 : "", "\t", "\n"
    """
    
    print("    abc  def       ".strip())
    # abc  def  (앞 뒤 공백들이 날아감)
    
    print("   \t  \n abc  def \n\n\n".strip())
    # abc  def  (앞 뒤 화이트스페이스들이 전부 날아감)

    with open('data/chicken.txt', 'r', encoding='utf-8') as f:
        for line in f:
            print(line.strip())  # 줄마다 있던 공백 제거됨

     

    split

    """
    split
    해당 파라미터를 기준으로 문자열을 나눔
    """
    
    my_string = "1. 2. 3. 4. 5. 6"
    print(my_string.split("."))
    # ['1', ' 2', ' 3', ' 4', ' 5', ' 6']
    
    """
    거슬리는 띄어쓰기를 없애려면?
    문자열 나누는 기준을 ". " (점 띄어쓰기)로 한다
    """
    
    print(my_string.split(". "))
    # ['1', '2', '3', '4', '5', '6']
    
    full_name = "Kim, Yuna"
    print(full_name.split(","))
    # ['Kim', ' Yuna']
    # ' Yuna'에 있는 띄어쓰기 없애려면 마찬가지로 ", "를 기준으로 설정
    
    full_name = "Kim, Yuna"
    print(full_name.split(", "))
    # ['Kim', 'Yuna']
    
    my_name = "hungry_bellybutton"
    name_data = my_name.split("_")
    last_name = name_data[0]
    first_name = name_data[1]
    print(first_name, last_name)
    # bellybutton hungry
    
    """
    어떤 걸 기준으로 나눠야 할까?
    print("    \n\n  2 \t  3 \n 5 7 11 \n \n")
    """
    
    # 화이트스페이스를 기준으로 나누고 싶으면 
    print("    \n\n  2 \t  3 \n 5 7 11 \n \n".split())
    # ['2', '3', '5', '7', '11']
    
    numbers = "    \n\n  2 \t  3 \n 5 7 11 \n \n".split()
    print(numbers[0] + numbers[1])
    # 23
    # split을 이용해서 리스트를 만든 값은 모두 "문자열"임!
    
    numbers = "    \n\n  2 \t  3 \n 5 7 11 \n \n".split()
    print(int(numbers[0]) + int(numbers[1]))
    # 5

     

    코딩에 빠진 닭

    # 변수
    sale_amount = 0  # 매출합
    days = 0  # 일자 수
    
    # 파일 열어서 split으로 구분
    with open('data/chicken.txt', 'r') as f:
        for line in f:
            list = line.split("일:")
            days += 1
            sale_amount += int(list[1])
      
    # 평균 매출액 구하기
    ave_sale = sale_amount / days
    print(ave_sale)
    with open('data/chicken.txt', 'r') as f:
        total_revenue = 0
        total_days = 0
        
        for line in f:
            data = line.strip().split(": ")
            revenue = int(data[1])  # 그날의 매출
    
            total_revenue += revenue
            total_days += 1
    
        print(total_revenue / total_days)
    line = "19일: 434500\n"
    data = line.strip().split(": ")
    print(data)  # ['19일', '434500']
    print(data[1])  # 434500

     

    파일 쓰기

    # w(write)모드 = 새로쓰기
    with open('new_file.txt', 'w') as f:
        f.write("Hello world!")
        f.write("My name is Codeit.")
    
    with open('new_file.txt', 'w') as f:
        f.write("Hello world!\n") # 개행문자를 넣어서 한 줄씩 띄워줌
        f.write("My name is Codeit.\n")
    
    '''
    마지막에 작성한 글이 처음에 작성한 글을 덮어씀.
    만약 덮어쓰는게 아니라 기존 파일에 추가하고 싶다면?
    '''
    
    # a(append)모드 = 추가
    with open('new_file.txt', 'a') as f:
        f.write("Hello world!\n")
        f.write("My name is Codeit.\n")
    
    '''
    new_file이 있으면 -> 기존 내용에 추가하기
    new_file이 없으면 -> 새로 만들기
    '''

    개행문자 추가


    단어장 만들기

    with open('vocabulary.txt', 'w') as f:
    	while True:
    		eng = input("영어 단어를 입력하세요: ")
    		# q를 입력하면 프로그램 종료료
    		if eng == 'q':
    			break
    
    		kor = input("한국어 뜻을 입력하세요: ")
    		# q를 입력하면 프로그램 종료
    		if kor == 'q':
    			break
            
            # 파일에 영어:한글 기록
    		f.write("{}: {}\n".format(eng, kor))


    단어 퀴즈

    with open('vocabulary.txt', 'r', encoding='utf-8') as f:
    	for line in f:
    		data = line.strip().split(": ")  # 영/한 단어를 쪼개서 리스트에 한 줄씩 넣어줌
    
    		guess = input("{}: ".format(data[1]))  # data[1]은 한글
    		if guess == data[0]:  # data[0]은 영어
    			print("맞았습니다!")
    		else:
    			print("아쉽습니다. 정답은 {}입니다.".format(data[0]))
                
    # 한 줄을 split(": ")로 분리했으므로 data 리스트에는 항상 2개의 요소만 들어감.


    고급 단어장

    import random
    
    voca_dict = {}
    
    with (open('vocabulary.txt', 'r', encoding='utf-8') as f):
    	for line in f:
        
    		# key는 사용자가 입력해야 할 영단어
    		# value는 컴퓨터가 출력해야 할 한글뜻
    		key, value = line.strip().split(": ")
    		voca_dict[key] = value
    		
    		# random.choice()함수를 사용하여 voca_dict.keys() 요소들 중 하나를 랜덤하게 선택
            # 딕셔너리 voca_dict의 키(key)들을 리스트로 변환홤.
    		random_key = random.choice(list(voca_dict.keys()))
            
            # random_key에 맞는 random_value 생성
    		random_value = voca_dict[random_key]
            
            # 한글뜻 random_value를 주면 사용자가 입력한 단어가 guess에 저장됨
    		guess = input("{}: ".format(random_value))
            
    		if guess != 'q':  
    			if guess == random_key:  # 랜덤 생성된 영단어가 guess와 일치하면 맞았다고 출력
    				print("맞았습니다!")
    			else:  # 틀렸으면 정답을 표시해줌.
    				print("아쉽습니다. 정답은 {}입니다.".format(random_key))
    		else:  # guess가 q이면 종료
    			break

    import random
    
    # 사전 만들기
    vocab = {}
    with open('vocabulary.txt', 'r') as f:
        for line in f:
            data = line.strip().split(": ")
            english_word, korean_word = data[0], data[1]
            vocab[english_word] = korean_word
    
    # 목록 가져오기
    keys = list(vocab.keys())
    
    # 문제 내기
    while True:
        # 랜덤한 문제 받아 오기
        index = random.randint(0, len(keys) - 1)
        english_word = keys[index]
        korean_word = vocab[english_word]
        
        # 유저 입력값 받기
        guess = input("{}: ".format(korean_word))
        
        # 프로그램 끝내기
        if guess == 'q':
            break
        
        # 정답 확인하기
        if guess == english_word:
            print("정답입니다!\n")
        else:
            print("틀렸습니다. 정답은 {}입니다.\n".format(english_word))

    4. 프로젝트: 로또 시뮬레이션

    로또 시뮬레이션: 1) 번호 뽑기

    from random import randint
    
    def generate_numbers(n):
        numbers = []
        i = 0
        
        while i < n:
            number = randint(1, 45)
            if number not in numbers:
               numbers.insert(i, number)
            else:
                continue
            i += 1
        
        return numbers
    
    # 테스트 코드
    print(generate_numbers(6))

    • 변수 i 대신 리스트의 길이 len()함수를 사용하면 코드가 줄어듦.

    왜냐하면 숫자를 하나씩 넣을 때마다 리스트의 길이도 그에 맞게 하나씩 커지니까.

    • insert 대신 append를 사용하면 코드가 더 간단해짐.

    함수 만들었으면 꼭 return값 반환하기

    # 모범답안 
    
    from random import randint
    
    def generate_numbers(n):
    	numbers = []
    
    	while len(numbers) < n:
    		num = randint(1, 45)
    		if num not in numbers:
    			numbers.append(num)
    
    	return numbers

     

    randint 사용 방법

    import random
    random.randint()
    
    from random import randint
    randint()

     

    로또 시뮬레이션: 2) 당첨 번호 뽑기

    from random import randint
    
    
    def generate_numbers(n):
    	numbers = []
    
    	while len(numbers) < n:
    		num = randint(1, 45)
    		if num not in numbers:
    			numbers.append(num)
    
    	return numbers
    
    
    def draw_winning_numbers():
        numbers = []
        
        while len(numbers) < 6:
            num = randint(1, 45)
            
            if num not in numbers:
                numbers.append(num)
        
        new_numbers = sorted(numbers)
        
        while True:
            bonus_number = randint(1,45)
            if bonus_number not in new_numbers:
                new_numbers.append(bonus_number)
                break
            else:
                continue
            
        return new_numbers
    
    # 테스트 코드
    print(draw_winning_numbers())

    • draw_winning_numbers()는 generate_numbers 활용하라고 해서 아무 생각없이 긁어 왔는데 그럴 필요가 없음.

    draw 함수 그대로 (숫자 6개) 정렬시키기 + 숫자 1개 뒤에 이어 붙이기

    → draw 함수에 7을 넣어서 숫자 7개 만들고 슬라이싱 (6개 - 정렬 / 1개)

    # 모범답안 
    
    from random import randint
    
    def generate_numbers(n):
    	numbers = []
    
    	while len(numbers) < n:
    		num = randint(1, 45)
    		if num not in numbers:
    			numbers.append(num)
    
    	return numbers
    
    def draw_winning_numbers():
    	winning_numbers = generate_numbers(7)
    	return sorted(winning_numbers[:6]) + winning_numbers[6:])


    로또 시뮬레이션: 3) 겹치는 번호 개수

    def count_matching_numbers(numbers, winning_numbers):
        
        count = 0
        
        for number in numbers:
            if number in winning_numbers:
                count += 1
                
        return count
    
    # 테스트 코드
    print(count_matching_numbers([2, 7, 11, 14, 25, 40], [2, 11, 13, 14, 30, 35]))  #3
    print(count_matching_numbers([2, 7, 11, 14, 25, 40], [14]))  #1


    로또 시뮬레이션: 4) 당첨금 확인

    def check(numbers, winning_numbers):
        count = count_matching_numbers(numbers, winning_numbers)
    
        if winning_numbers[6] in numbers:
            if count == 6:
                return 50000000
        else:
            if count == 6:
                return 1000000000
            elif count == 5:
                return 1000000
            elif count == 4:
                return 50000
            elif count == 3:
                return 5000
    
    # 테스트 코드
    print(check([2, 4, 11, 14, 25, 40], [4, 12, 14, 28, 40, 41, 6]))  # 5000
    print(check([2, 4, 11, 14, 25, 40], [2, 4, 10, 11, 14, 40, 25]))  # 50000000
    # 모범답안
    
    def check(numbers, winning_numbers):
        count = count_matching_numbers(numbers, winning_numbers[:6])
        bonus_count = count_matching_numbers(numbers, winning_numbers[6:])
    
        if count == 6:
            return 1000000000
        elif count == 5 and bonus_count == 1:
            return 50000000
        elif count == 5:
            return 1000000
        elif count == 4:
            return 50000
        elif count == 3:
            return 5000
        else:
            return 0
    
    
    # 테스트 코드
    print(check([2, 4, 11, 14, 25, 40], [4, 12, 14, 28, 40, 41, 6]))
    print(check([2, 4, 11, 14, 25, 40], [2, 4, 10, 11, 14, 40, 25]))

      함수 슬라이싱을 이용하여 count와 bonus_count 변수를 만들었음.


    로또 시뮬레이션: 5) 코드 하나로 합치기


    5. 프로젝트: 숫자 야구

     

    숫자 야구: 코드 하나로 합치기

    from random import randint
    
    # 랜덤으로 숫자 생성
    def generate_numbers():
        numbers = []
        i = 0
        while i < 3:
            a = randint(0, 9)
            if a not in numbers:
                numbers.insert(i, a)
            i += 1
        
        print("0과 9 사이의 서로 다른 숫자 3개를 랜덤한 순서로 뽑았습니다.\n")
        return numbers
    
    
    # 숫자 예측
    def take_guess():
        print("숫자 3개를 하나씩 차례대로 입력하세요.")
        
        new_guess = []
        i = 0
        while i < 3:
            num = int(input("{}번째 숫자를 입력하세요: ".format(i)))
            if num < 0 or num > 9:
                print("범위를 벗어나는 숫자입니다. 다시 입력하세요.")
            else:
                if num not in new_guess:
                    new_guess.append(num)
                    i += 1
                else: 
                    print("중복되는 숫자입니다. 다시 입력하세요.")
                
        return new_guess
    
    
    # 점수계산
    def get_score(guesses, solution):
        strike_count = 0
        ball_count = 0
        i = 0
        
        while i < len(guesses):
            if guesses[i] in solution:
                if guesses[i] == solution[i]:
                    strike_count += 1
                else:
                    ball_count += 1        
            i += 1
    
        return strike_count, ball_count
    
    
    # 여기서부터 게임 시작!
    ANSWER = generate_numbers()
    tries = 0
    
    while True:
        guess = take_guess()
        strike, ball = get_score(guess, ANSWER)
        tries += 1
        print("{}S, {}B".format(strike, ball))
    
        if strike == 3 and ball == 0:
            print("축하합니다. {}번 만에 숫자 3개의 값과 위치를 모두 맞히셨습니다.".format(tries))
            break

    # 모범답안
    
    from random import randint
    
    
    def generate_numbers():
        numbers = []
    
        while len(numbers) < 3:
            new_number = randint(0, 9)
            if new_number not in numbers:
                numbers.append(new_number)
    
        return numbers
    
    
    def take_guess():
        new_guess = []
        while len(new_guess) < 3:
            num = int(input("{}번째 수를 입력하세요: ".format(len(new_guess) + 1)))
    
            if num < 0 or num > 9:
                print("0에서 9까지의 수를 입력해 주세요!")
            elif num in new_guess:
                print("중복되는 숫자입니다. 다시 입력하세요.")
            else:
                new_guess.append(num)
    
        return new_guess
    
    
    def get_score(guesses, solution):
        strike_count = 0
        ball_count = 0
    
        for i in range(3):
            if guesses[i] == solution[i]:
                strike_count += 1
            elif guesses[i] in solution:
                ball_count += 1
    
        return strike_count, ball_count
    
    
    # 여기서부터 게임 시작!
    ANSWER = generate_numbers()
    tries = 0
    
    while True:
        user_guess = take_guess()
        s, b = get_score(user_guess, ANSWER)
    
        print("{}S {}B\n".format(s, b))
        tries += 1
    
        if s == 3:
            break
    
    print("축하합니다. {}번 만에 세 숫자의 값과 위치를 모두 맞히셨습니다.".format(tries))

     

    728x90