[제로베이스_데이터 취업 스쿨 16기](6/16 ~ 18) - 예외 처리

jumee·2023년 6월 20일
0
post-thumbnail

중급 연습 문제풀이 - 예외 처리

파이썬의 예외 처리 문법을 활용한 문제 풀이

EX 1. 사용자가 입력한 숫자를 이용해서 산술연산 결과를 출력하는 모듈을 만들되, 예상하는 예외에 대한 예외처리 코드를 작성해보자.

def add(n1,n2):
    print('덧셈 연산')

		try: # 숫자가 들어왔는지 확인
				n1 = float(n1)
		except:
				print('첫 번째 피연산자는 숫자가 아닙니다.')
				return 
    
		try: # 숫자가 들어왔는지 확인
				n2 = float(n2)
		except:
				print('두 번째 피연산자는 숫자가 아닙니다.')
				return 
    
		print(f'{n1} + {n2} = {n1 + n2}')

def sub(n1,n2):
    print('뺄셈 연산')

		try: # 숫자가 들어왔는지 확인
				n1 = float(n1)
		except:
				print('첫 번째 피연산자는 숫자가 아닙니다.')
				return 
		
		try: # 숫자가 들어왔는지 확인
				n2 = float(n2)
		except:
				print('두 번째 피연산자는 숫자가 아닙니다.')
				return 
   
    print(f'{n1} - {n2} = {n1 - n2}')

def mul(n1,n2):
    print('곱셈 연산')

		try: # 숫자가 들어왔는지 확인
				n1 = float(n1)
		except:
				print('첫 번째 피연산자는 숫자가 아닙니다.')
				return 
    

		try: # 숫자가 들어왔는지 확인
				n2 = float(n2)
		except:
				print('두 번째 피연산자는 숫자가 아닙니다.')
				return 
    
    print(f'{n1} * {n2} = {n1 * n2}')

def div(n1,n2):
    print('나눗셈 연산')

		try: # 숫자가 들어왔는지 확인
				n1 = float(n1)
		except:
				print('첫 번째 피연산자는 숫자가 아닙니다.')
				return 
    

		try: # 숫자가 들어왔는지 확인
				n2 = float(n2)
		except:
				print('두 번째 피연산자는 숫자가 아닙니다.')
				return 
		
		if n2 == 0:  
        print('0으로 나눌 수 없습니다.')
				return 
		
		print(f'{n1} / {n2} = {n1 / n2}')

def mod(n1,n2):
    print('나머지 연산')

		try: # 숫자가 들어왔는지 확인
				n1 = float(n1)
		except:
				print('첫 번째 피연산자는 숫자가 아닙니다.')
				return 
    

		try: # 숫자가 들어왔는지 확인
				n2 = float(n2)
		except:
				print('두 번째 피연산자는 숫자가 아닙니다.')
				return 

		if n2 == 0:  
        print('0으로 나눌 수 없습니다.')
				return 
		
		print(f'{n1} % {n2} = {n1 % n2}')

def flo(n1,n2):
    print('몫 연산')

		try: # 숫자가 들어왔는지 확인
				n1 = float(n1)
		except:
				print('첫 번째 피연산자는 숫자가 아닙니다.')
				return 
    

		try: # 숫자가 들어왔는지 확인
				n2 = float(n2)
		except:
				print('두 번째 피연산자는 숫자가 아닙니다.')
				return 
 
   if n2 == 0:
				print('0으로 나눌 수 없습니다.')
				return 
        
	 print(f'{n1} // {n2} = {n1 // n2}')
    
def exp(n1,n2):
    print('거듭제곱 연산')

		try: # 숫자가 들어왔는지 확인
				n1 = float(n1)
		except:
				print('첫 번째 피연산자는 숫자가 아닙니다.')
				return 
    

		try: # 숫자가 들어왔는지 확인
				n2 = float(n2)
		except:
				print('두 번째 피연산자는 숫자가 아닙니다.')
				return 

    print(f'{n1} ** {n2} = {n1 ** n2}')
import calculator as cc

n1 = int(input('첫번째 피연산자 입력: '))
n2 = int(input('두번째 피연산자 입력: '))

cc.add(n1,n2)
cc.sub(n1,n2)
cc.mul(n1,n2)
cc.div(n1,n2)
cc.mod(n1,n2)
cc.flo(n1,n2)
cc.exp(n1,n2)

✅ 또는 0이 들어왔을 때 예외 처리를 다음과 같이 Exception 클래스를 사용할 수 도 있다.

try:
		print(f'{n1} / {n2} = {n1 / n2}')
except ZeroDivisionError as e:
		print(e) # 어떤 방식으로 에러가 나는지 확인하고
		print('0으로 나눌 수 없습니다.')

# 결과는 다음과 같이 나올 것이다 #
# float division by zero
# 0으로 나눌 수 없습니다. 

EX 2. 1부터 1000까지의 소수인 난수 10개를 생성하되, 소수가 아니면 사용자 예외가 발생하도록 프로그램을 만들자.

# prime.py
class NotPrimeException(Exception): # 소수가 아닐 때 사용할 클래스

    def __init__(self,n):
        super().__init__(f'{n} is not prime number.')

class PrimeException(Exception): # 소수일 때 사용할 클래스

    def __init__(self,n):
        super().__init__(f'{n} is prime number.')

def isPrime(number): # 소수인지 확인해주는 기능
    flag = True # 소수인지 아닌지를 판별하기 위한 불린 초기화
    for i in range(2,number): # 2와 number -1 한 값들만 확인해주면 된다.
        if number % i == 0:
            flag = False
            break

    if flag == False: # 소수가 아니라면
        raise NotPrimeException(number)
    else:
        raise PrimeException(number)
# 난수이면서, 소수인 숫자를 출력해야 한다.
# 소수가 아니면 예외를 발생시키자
import prime as pm
import random
primeNumbers = []
n = 0
while n < 10:
    rn = random.randint(2,1000) # 소수에는 일단 1이 포함 안됨.
    if rn not in primeNumbers: # 일단, 난수가 primeNumbers 안에 이미 있는지 확인
        try:
            pm.isPrime(rn) # 소수인지 확인하는 함수
        except pm.NotPrimeException as e: # 소수가 아닌 강제 예외가 발생하면
            print(e)
            continue
        except pm.PrimeException as e: # 소수일 때 강제 예외
            print(e)
            primeNumbers.append(rn)
    else:
        print(f'{rn} 은 이미 존재합니다.')
        continue

    n += 1

print(f'소수인 난수 결과 : {primeNumbers}')

EX 3. 상품 구매에 따른 ‘총 구매 금액’을 출력하되 개수가 잘 못 입력된 경우 별도로 출력하도록 프로그램을 만들자.

# calculatorPrice.py

g1 = 1000; g2 = 1200; g3 = 800;
g4 = 2000; g5 = 900

def formatedNumber(n):
	retur n format(n, ',')

def calculator(*gcs): #  상품을 몇개를 구매할지 확정되지 않았기 때문에 -> 반복가능한 객체로 사용할 수 있다

    gdDic = {} # 제대로 된 상품 목록을 저장할 딕셔너리 초기화
    againCntInput = {} # 미결제된 상품 목록을 저장할 딕셔너리 초기화

    for idx, gc in enumerate(gcs):
        try:
            gdDic[f'g{idx + 1}'] = int(gc)
        except Exception as e: # int() 를 해줬을 때, 오류가 발생하면 againCntInput 딕셔너리에 담기
            againCntInput[f'g{idx + 1}'] = gc
            print(e)

    # 총금액 계산해주기
    tot_price = 0
    for g in gdDic.keys():
        tot_price += globals()[f'{g}'] * gdDic[g] # globals() 는 전역변수를 담고 있는 리스트다

    print('-'*32)
    print(f'총 구매 금액: {formatedNumber(tot_price)}원')
    print('-'*16, '미결제 항목', '-'*16)
    for a in againCntInput.keys():
        print(f'상품 이름: {a},\t 구매 개수: {againCntInput[a]}')
    print('-' * 32)
		
import calculatorPrice as cp

# 구매할 상품 개수를 입력받자
gd1 = input('goods1 구매 개수: ')
gd2 = input('goods2 구매 개수: ')
gd3 = input('goods3 구매 개수: ')
gd4 = input('goods4 구매 개수: ')
gd5 = input('goods5 구매 개수: ')

acp.calculator(gd1,gd2,gd3,gd4,gd5)

🔥 globals() 🔥 : 저장된 전역변수들을 리스트로 불러온다.

EX 4. 회원가입 프로그램을 만들되, 입력하지 않은 항목이 있는 경우, 에러 메세지를 출력하는 프로그램을 만들자.

# signinCheck

class EmptyDataException(Exception):
		
		def __init__(self,i): # 어떤 값이 없는지를 받아야되니까
				super().__init__(f'{i} is empty!!')

def checkInfo(n,m,p,a,c): # 실행파일에서 회원의 정보를 입력받으면
		
		if n == '': # 이름이 비어있다면 error 발생
				raise EmptyDataException('name')
		elif m == '':
				raise EmptyDataException('mail')
		elif p == '':
				raise EmptyDataException('passsword')
		elif a == '':
				raise EmptyDataException('address')
		elif c == '':
				raise EmptyDataException('phone number')
	

class RegistMember():

		def __init__(self, n,m,p,a,c): # 회원 정보를 입력받는 함수
				self.name = n
				self.mail = m
				self.pw = p
				self.address = a
				self.contact = c
				print('Membership registered!!')

		def printUserInfo(self):
				print(f'name : {self.name}')
				print(f'mail : {self.mail}')
				print(f'password: {self.pw}')
				print( f'address : {self.address}')
				print(f'contact : {self.contact}')
# 실행파일에서 input을 받는다.
import signinCheck as sc

name = input('이름 입력: ')
mail = input('메일 주소 입력: ')
pw = input('비밀번호 입력: ')
address = input('주소 입력: ')
contact = input('연락처 입력: ')

# 함수 실행 시 예외 발생 처리
try:
		sc.checkInfo(name,mail,pw,address,contact)
		newMember = sc.RegistMember(name,mail,pw,address,contact)
		newMember.printUserInfo()

except sc.EmptyDataException as e:
		print(e)
		

# 결과 출력

EX 5. 예외처리를 이용해서 은행 계좌 개설 및 입/출금 프로그램을 만들자.

# bank.py

# 1. 은행에 대한 클래스
class Bank:

    def __init__(self):
        self.accounts = {}

    def addAccount(self,privateBank): # 계좌에 추가해주는 함수
        self.accounts[privateBank.account_no] = privateBank

    def isAccount(self, accountNo):# 계좌를 추가할 때, 기존에 있는 계좌인지 확인해주는 함수
        return accountNo in self.accounts

    def doDeposit(self,accountNo, m): # 입금하는 함수
        pb = self.accounts[accountNo] # 입력한 계좌에 해당하는 정보를 가져오고
        pb.totalMoney = pb.totalMoney + m # 계좌 정보에 들어있는 잔고에서 더해주기

    def doWithdraw(self,accountNo, m): # 출금하는 함수
        pb = self.accounts[accountNo] # 입력한 계좌에 해당하는 정보를 가져오고
        # 그 잔고와 출금하려는 금액에 따라 출금이 가능한지 아닌지를 확인해주기
        if pb.totalMoney - m < 0: # 부족하면
            raise LackException(pb.totalMoney, m) # 예외 처리
        pb.totalMoney = pb.totalMoney - m # 부족하지 않으면

class LackException(Exception): # 잔고가 부족할 때 발생할 예외 함수

    def __init__(self, m1, m2): # 잔고와 출금하려는 금액을 받아온다.
        super().__init__(f'잔고 부족!, 잔액 : {m1}, 출금시도액: {m2}')

# 2. 개인통장을 만들어내는 클래스
# 은행, 계좌 번호, 잔고 등에 대한 정보를 갖고 있어야 한다.
# 계좌 번호를 랜덤하게 생성하기 위해 random 모듈을 가져오자
import random

class PrivateBank:

    def __init__(self, bank, account_name):
        self.bank = bank # 은행 이름
        self.account_name = account_name # 계좌 이름

        while True:
            newAccount = random.randint(10000,99999) # 임의의 계좌 번호를 발생시키고
            if bank.isAccount(newAccount): # 이미 계좌 번호가 존재한다면
                continue # 중복되지 않는 계좌 번호가 나올때까지 반복 실행
            else:
                self.account_no = newAccount # 중복되지 않은 계좌번호가 만들어지면
                break  # 반복문 탈출

        self.totalMoney = 0 # 계좌 잔고 초기화

        bank.addAccount(self) # 내 계좌 정보를 추가해주기

    # 내 계좌정보 출력하는 함수
    def printAccount(self):
        print('-'*40)
        print(f'account name: {self.account_name}')
        print(f'account number: {self.account_no}')
        print(f'account total money: {self.totalMoney}')
        print('-'*40)
import bank

# 가상의 은행 먼저 만들기
koreaBank = bank.Bank()

new_account_name = input('통장 개설을 위한 예금주 입력: ')

# 새로운 계좌 등록후, 정보 출력
myAccount = bank.PrivateBank(koreaBank, new_account_name)
myAccount.printAccount()

# 입출금 활동 시작
while True:
    selectNumber = int(input('1.입금 \t 2.출금 \t 3.종료'))
    if selectNumber == 1: # 입금
        m = int(input('입금액 입력: '))
        koreaBank.doDeposit(myAccount.account_no, m)
        myAccount.printAccount()

    elif selectNumber == 2: # 출금
        m = int(input('출금액 입력: '))
        try:
            koreaBank.doWithdraw(myAccount.account_no, m)
        except bank.LackException as e:
            print(e)
        # 예외가 발생하던, 발생하지 않던 계좌정보는 한번 더 출력해주기
        finally:
            myAccount.printAccount()

    elif selectNumber == 3: # 종료를 누르면
        print('Bye ~')
        break

    else: # 1,2,3이 아닌 다른 번호를 입력했을 때
        print('잘못 입력했습니다. 다시 선택하세요')

🔜 다음 스터디 노트..

다음 스터디 노트에는 텍스트 파일 다루기와 관련된 연습 문제 풀이를 정리한다.

profile
공부한 내용들에 대해 끄적이는 공간입니다💎

0개의 댓글