제목은 로또 번호 생성기로 하겠습니다 근데 이제 Iterator를 곁들인.🔨

Junyoung Lee·2021년 5월 16일
3

Python

목록 보기
1/6
post-thumbnail

이번엔 간단한 로또 번호 생성기를 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
        
        
        ...

setint형으로 넣게되면 순서가 정렬되어 버리기 때문에 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.numbersetset가 인덱스 사용이 불가하기 때문에 인덱스 사용과 더불어 수동으로 받은 숫자가 중복되어 출력되지 않게 리스트와 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개가 출력되게 만들었기 때문에 manualnum0인지 체크 후 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.mlistset로 변환하여 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로 만들기 모두 성공👏👏👏👏👏👏


제 글을 읽어주셔서 감사하고 혹시 문제있는 부분 있으면 댓글로 남겨주시면 감사하겠습니다!
아이디어 주신 희수님께도 감사인사를 전하며 다음엔 재미없는 글로 돌아오겠습니다🤣











Github에서 코드보기

profile
🎹재즈를 사랑하는 백엔드 개발자 이준영입니다🎷

6개의 댓글

comment-user-thumbnail
2021년 5월 17일

수고하셨습니다

1개의 답글
comment-user-thumbnail
2021년 5월 17일

와! 좋은 아이디어 배워갑니다!

1개의 답글
comment-user-thumbnail
2021년 5월 17일

많이 배우고 갑니다~~~ 🤗🤗🤗

1개의 답글