이번엔 간단한 로또 번호 생성기를 Iterator
로 만들어 보았습니다!
스터디중에 팀원 한분이 로또 번호 생성기 같은걸 만들어 보면 연습에 좋을 것 같다고 하셔서 만들게 되었는데 random
, numpy
를 사용해서 만들기는 너무 뻔하고 Iterator
가 아직 정리도 잘 안되어 연습도 할 겸 지금까지 알고 있는 지식들을 최대한 이용하여 도전해보기로 했습니다!
아침에 자다 깨서 멍하게 빗소리를 들으며 가만히 있다가 갑자기 생각나서 머릿속으로 대충 구상하고 일어나서 바로 작업에 들어갔습니다!
random
, numpy
를 사용하지 않기로 한 이상 랜덤으로 숫자가 나오게하는 방법은 set
밖에 떠오르지 않아서 set
로 숫자를 입력하면 입력한 만큼 로또번호 세트가 출력되게 간단하게 만들어 보기로 했습니다!
class LottoNumberGenerator:
def __init__(self, maxnum):
self.start = 0
self.maxnum = maxnum
self.numberset = set(str(i) for i in range(1, 46))
def __iter__(self):
return self
...
set
는int
형으로 넣게되면 순서가 정렬되어 버리기 때문에str
로 type을 변환해서 변수에 저장했습니다!
하지만 큰 문제가 있었으니...😱
몰랐습니다.. set
를 호출해도 종료 전에는 전부 다 똑같은 순서로 호출된다는 것을...
# 출력
# 출력할 로또번호 세트 입력 : 5
# {'6', '35', '19', '33', '1', '42'}
# {'6', '35', '19', '33', '1', '42'}
# {'6', '35', '19', '33', '1', '42'}
# {'6', '35', '19', '33', '1', '42'}
# {'6', '35', '19', '33', '1', '42'}
__next__
쪽에 새로 호출했는데도 변하지 않았기 때문에 현재로선 아무리 생각해도 별 다른 방법이 떠오르지 않아서 그냥 한 세트만 출력하는걸로 방향을 바꿨습니다😥
한 세트만 출력하는 기능은 쉽게 끝날 것 같아서 반자동 기능을 추가하기로 했습니다!
아래부턴 정확한 과정을 남기지 못해서 완성된 코드로 코멘트를 달아보려고합니다!
class LottoNumberGenerator:
def __init__(self, manualnum):
self.start = manualnum
self.maxnum = 6
self.manualnum = manualnum
self.mlist = []
self.numberset = list(map(int, set(str(i) for i in range(1, 46)))) #세트의 인덱스 사용을
#위해 리스트로 변환
수동으로 숫자를 입력할 갯수를 입력받기 위해
manualnum
을 추가하고self.start
는 총 출력숫자 계산을 위해manualnum
과 같은 숫자로 입력받게 하였습니다!
self.numberset
은set
가 인덱스 사용이 불가하기 때문에 인덱스 사용과 더불어 수동으로 받은 숫자가 중복되어 출력되지 않게 리스트와int
형으로 다시 변경했습니다😊
def __iter__(self):
return self
iterable
객체를 만들기 위해__iter__
를 추가했습니다!
def __next__(self):
if self.start < self.maxnum and self.manualnum == 0: # 자동
n = self.numberset[self.start]
self.start += 1
return n
elif self.start < self.maxnum and 0 < self.manualnum < 6: # 반자동
if len(self.mlist):
n = self.numberset[self.start]
self.start += 1
return n
else:
self.mlist =
list(map(int, input('위에 입력한 개수만큼 수동으로 사용할 번호 입력 (공백으로 구분): ').split()))
if len(set(self.mlist)) != self.manualnum or max(self.mlist) > 45 or min(self.mlist) < 1:
raise NumberError
self.numberset = [i for i in self.numberset if i not in self.mlist]
# 👆수동으로 넣은 번호 삭제
return self.mlist
elif self.manualnum > 5 or self.manualnum < 0:
raise NumberError
else:
raise StopIteration
이곳을 참 복잡하게 만들었는데요.. 제 실력이 아직 여기까지 밖에 안되는 것 같습니다😰
처음if
부분은 숫자를0
을 입력하게 되면 자동으로 6개가 출력되게 만들었기 때문에manualnum
을0
인지 체크 후 6개 숫자를return
하게 만들었습니다!반자동을 출력할 수 있는
elif
부분은 따로 아래 다시 적어보겠습니다!
elif self.start < self.maxnum and 0 < self.manualnum < 6: # 반자동
if len(self.mlist):
n = self.numberset[self.start]
self.start += 1
return n
else:
self.mlist =
list(map(int, input('위에 입력한 개수만큼 수동으로 사용할 번호 입력 (공백으로 구분): ').split()))
if len(set(self.mlist)) != self.manualnum or max(self.mlist) > 45 or min(self.mlist) < 1:
raise NumberError
self.numberset = [i for i in self.numberset if i not in self.mlist]
# 👆수동으로 넣은 번호 삭제
return self.mlist
첫
if
문은len(self.mlist)
에 이미 숫자가 들어있으면 바로 다음 숫자를 출력할 수 있게 처리했습니다!
else
부분은 숫자를 받고 숫자가 중복으로 들어왔는지 체크를 위해서self.mlist
를set
로 변환하여len
을 사용하여 처음 입력받았던 숫자와 같은 양의 숫자가 들어왔는지
체크 및max
,min
함수를 사용하여 받은 값이 범위 안에 들어오는지 체크하였습니다!그 후 수동으로 입력되어 리스트와 중복 되는 숫자를
self.numberset
에서 제거해줬습니다!self.numberset = [i for i in self.numberset if i not in self.mlist]
class NumberError(Exception):
def __init__(self):
super().__init__('숫자를 잘못 입력하셨습니다.')
숫자를 잘못 입력 할 경우 발생하는
NumberError
도 하나 추가해봤습니다😆
여기까지가 Iterator
부분이고 아래부터는 출력을 위한 코드입니다.
Mnum = int(input('자동은 "0" 입력 반자동은 "1 - 5"사이 입력 : '))
output = []
for i in LottoNumberGenerator(Mnum):
if type(i) == list:
output += i
else:
output.append(i)
output.sort()
print('추천 번호는', output, '입니다!')
마지막 출력을 위해서 수동으로 입력받았을때는
list
를 리턴받아 마지막 최종 출력에 합쳐지게 만들었습니다!
숫자 정리를 위해서sort
를 이용해 깔끔하게 출력될 수 있도록 했습니다🤗
작동도 잘 하네요! 여러번 테스트 해봤지만 아직까진 버그는 없는 것 같습니다🎈
다른분들이 보기엔 코드가 쓸데없이 길고 복잡하게 보일 수 있겠지만 처음으로 만들어본 입장에서는 그래도 나름 잘 만들었다고 생각됩니다ㅋㅋㅋㅋ
원래 목적이었던
random
,numpy
쓰지 않기와Iterator
로 만들기 모두 성공👏👏👏👏👏👏
제 글을 읽어주셔서 감사하고 혹시 문제있는 부분 있으면 댓글로 남겨주시면 감사하겠습니다!
아이디어 주신 희수님께도 감사인사를 전하며 다음엔 재미없는 글로 돌아오겠습니다🤣
수고하셨습니다