13주차 목 1116 (이터레이터, 제너레이터, 정규표현식) :: newb

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 13주차 목 1116 (이터레이터, 제너레이터, 정규표현식)
    광주인력개발원 일일포스팅(메모장) 2023. 11. 16. 16:53
    728x90
    반응형
    <이터레이터(Iterator)>
    파이썬에서 반복 가능한 객체(클래스)를 표현하는데 사용되는 인터페이스
    이터레이터는 iter()함수와 next()함수를 이용하여 반복(Iterator)을 수행함
    ### 클래스 정의하기
    class MyIterator :
        ### 클래스 생성자 정의하기
        def __init__(self) :
            self.cuurent_value = 0
            print(f"#1 (__init__) : self={self} / self.cuurent_value={self.cuurent_value}")
            
        ### 자신의 클래스를 반환하는 iter 함수 정의
        def __iter__(self) :
            print(f"#2 (__iter__) : self={self}")
            return self
    
        ### 반복을 수행하는 next 함수 정의
        def __next__(self) :
            print(f"#3 (__next__) : self={self}")
            ### current_value의 값이 5보다 작을 때까지 반복 수행
            if self.cuurent_value < 5 :
                # - 반환할 변수에 current_Value의 현재값 저장
                result = self.cuurent_value
                # - current_Value의 현재값을 1증가
                self.cuurent_value += 1
    
                print(f"#4 : result={result} / self.cuurent_value={self.cuurent_value}")
                # - result 값 반환
                return result
            else :
                print("5 : StopIterator 예외 발생!!")
                ### 이터레이터는 반복이 끝나면 종류시켜야함
                # - 종료시키는 방법은 강제로 오류 발생시킴
                raise StopIteration
    ### 이터레이터 실행시키기
    # - 클래스 생성하기
    my_iterator = MyIterator()
    #1 (__init__) : self=<__main__.MyIterator object at 0x00000170C96197D0> / self.cuurent_value=0
    ### 이터레이터 기능은 반복문 (for or while)을 사용해야만 작동하는 기능임
    # - 최초 __iter__() 함수를 호출하고,
    # - 출력 시 __next__() 함수가 한번씩 수행하면서 값을 반환받아서 출력함
    # - 한번 반환된 후 메모리는 초기화 되며, 다음 반복시 다시 메모리를 사용
    # ** 메모리를 효율적으로 활용할 수 있음
    
    # 반복 수행하여 result 값 출력하기
    for value in my_iterator :
        print(value)
    #2 (__iter__) : self=<__main__.MyIterator object at 0x00000170C96A9510>
    #3 (__next__) : self=<__main__.MyIterator object at 0x00000170C96A9510>
    #4 : result=0 / self.cuurent_value=1
    0
    #3 (__next__) : self=<__main__.MyIterator object at 0x00000170C96A9510>
    #4 : result=1 / self.cuurent_value=2
    1
    #3 (__next__) : self=<__main__.MyIterator object at 0x00000170C96A9510>
    #4 : result=2 / self.cuurent_value=3
    2
    #3 (__next__) : self=<__main__.MyIterator object at 0x00000170C96A9510>
    #4 : result=3 / self.cuurent_value=4
    3
    #3 (__next__) : self=<__main__.MyIterator object at 0x00000170C96A9510>
    #4 : result=4 / self.cuurent_value=5
    4
    #3 (__next__) : self=<__main__.MyIterator object at 0x00000170C96A9510>
    5 : StopIterator 예외 발생!!
    ### 문자열 "Hello" 의 각 문자 하나씩 출력하는 프로그램을 작성해주세요.."hello"
    for i in "Hello" :
        print(i)
    H
    e
    l
    l
    o

     

    내가 한 코드

    ### 이터레이터 클래스 생성해서 hello 각 단어 출력하기
    # - 임의 문자열을 받아서 처리
    # - 임의 문자열은 외부에서 클래스 생성시 넣어준다.
    class StringIterator:
        def __init__(self) :
            self.wd = self.get_string()
            self.index = 0
        def __iter__(self) :
            return self
        def __next__(self) :
            if self.index < len(self.wd) :
                result = self.wd[self.index]
                self.index += 1
                return result
            else :
                raise StopIteration
                
        def get_string(self) :
            return input("문자열 : ")
    iterator = StringIterator()
    for char in iterator:
        print(char)
    문자열 :  123456
    1
    2
    3
    4
    5
    6

     

    강사님 코드

    class StrintIterator :
        ### 클래스 생성자
        def __init__(self, p_text) :
            # - next함수에서 1씩 증가시키면서 반복 조건에 사용할 변수
            # - p_text는 지역변수
            # - text는 멤버변수
            self.index = 0
    
            # - 받아온 문자열
            self.text = p_text
            
        ### 반복수행을 위한 iter 함수 정의
        def __iter__(self) :
            return self
    
        ### 한건 한건 처리를 위한 next 함수 정의
        def __next__(self) :
            if self.index < len(self.text) :
                ### 문자열에서 문자 하나씩 추출하기
                result = self.text[self.index]
                self.index += 1
                return result
            else :
                raise StopIteration
    ### 이터레이터 기능 사용하기
    # 반복문을 이용해서 전체 반복하기
    # = 클래스 생성하기
    msg = "hello"
    string_iter = StrintIterator(msg)
    ### 반복문을 이용해서 전체 추출하기
    for char in string_iter :
        print(char)
    h
    e
    l
    l
    o

     

    <예제> 두개의 숫자(시작값, 종료값) 값을 이용해서 짝수값만 반환하는 이터레이터 만들기

     

    내가 한 코

    class EvenNumberIterator:
        def __init__(self):
            self.current = 0
        def __iter__(self):
            return self
        def __next__(self) :
            if self.current < 10:
                if self.current % 2 == 0:
                    result = self.current
                    self.current += 1
                    return result
                else:
                    self.current += 1
                    return self.__next__()
            else:
                raise StopIteration
    num_iter = EvenNumberIterator()
    for num in num_iter :
        print(num)
    0
    2
    4
    6
    8

     

    강사님 코드

    class EvenNumberIterator:
        def __init__(self,start, end):
    
            self.start = start
            self.end = end
        def __iter__(self) :
            return self
        def __next__(self) :
            ### start 부터 end 까지 무조건 반복 실행
            #- i 값은 사용 안함
            # - 사용하는 값은 self.start 값만 사용
            for i in range(self.start, self.end, 1):ㅗㅗ
                ### self.start가 짝수인지 체크
                if self.start % 2 == 0 :
                    ### 반환할 변수에 저장
                    result = self. start
                    # - self.start값은 1 증가
                    self.start +=1
                    # - 반환하기 : 반환하면 for 문은 종료됨
                    return result
                ### 짝수가 아니면
                else :
                    # - 1증가만 시키고 반복을 계속 수행
                    self.start +=1
            ### for 문을 이용한 경우에는, 이터레이터 반복 종료 후 마지막에 아래 추가
            raise StopIteration
    even_iter = EvenNumberIterator(1,10)
    
    for even in even_iter :
        print(even)
    2
    4
    6
    8
    <예제> 외부 함수를 이용해서 짝수값 추출하는 이터레이터 만들기>
    class EvenNumberIterator :
        ### 클래스 생성자 정의
        def __init__(self, start, end, func) :
            # - 시작값
            self.start = start
            # - 종료값
            self.end   = end
            # - 외부함수
            self.func  = func
    
        ### 반복을 위한 이터레이터 함수 정의
        def __iter__(self) :
            return self
    
        ### 반복 결과값을 처리할 함수 정의
        def __next__(self) :
            ### 시작부터 종료까지 while 반복
            while self.start <= self.end :
                ### 외부함수로 짝수 of 홀수 체크
                # - 짝수면 True 홀수면 False
                if self.func(self.start) :
                    result = self.start
                    self.start += 1
                    return result
                else :
                    self.start += 1
                ### 이터레이터 종료하기
                raise StopIteration
    ### 짝수와 홀수를 판별하는 외부함수 정의하기
    def is_even(num) :
        return num % 2 == 0
    ### 이터레이터 클래스 생성하기
    even_iter = EvenNumberIterator(1, 10, is_even)
    
    ### 이터레이터 반복 수행하기
    for even in even_iter :
        print(even)
    <예제> 텍스트 파일의 내용을 한줄씩 반환하는 이터레이터 만들기

     

    내가 한 코드

    class FileLineIterator:
        def __init__(self, filename, encoding="utf-8"):
            self.filename = filename
            self.file = open(filename, 'r', encoding=encoding)
    
        def __iter__(self):
            return self
    
        def __next__(self):
            line = self.file.readline()
            if line:
                return line
            else:
                self.file.close()
                raise StopIteration
    
    file_iter = FileLineIterator('./04_example.txt', encoding="utf-8")
    
    for line in file_iter:
        print(line, end='')
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⢷⣷⣣⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⠀⠀⠀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⢏⣿⣿⡵⡀⠀⠀⠀⠀⠀⠀⠀
    ⠀⠀⠀⠀⣠⣮⣷⣿⣿⣿⣿⣷⣄⣄⠀⠀⠀⠀⠈⢞⣿⣿⡵⡀⠀⠀⠀⠀⠀
     ⠀⠀⡠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⣏⢦⣤⡀⠀⠀⠀⠫⣻⣿⣾⢄⠀⠀⠀
     ⠀⣔⣿⣿⣿⣿⣿⣿⠿⣿⠻⢟⣿⣿⣿⣿⣿⡆⠀⠀⠀⠑⡿⣿⣯⢆⠀⠀
     ⢰⣸⢿⣻⢟⠃⠉⠉⠀⡠⠤⠸⣸⣿⣿⣿⡳⠁⠀⠀⠀⠀⡨⠺⠿⠇⢓⡄
     ⠧⠊⠁⠘⣖⣳⠠⣶⣋⡹⠁⠀⠛⣩⢻⠋⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⢾⠀
    ⠀⠀⢠⠂⠁⠓⠒⠊⠀⡠⠤⡀⢠⠀⠚⠀⠀⠀⠀⠀⡠⠊⢀⠤⡤⣔⠩⠼⡀
    ⠀⠀⢇⠀⠀⢀⡠⢔⣪⠠⠖⠇⡘⠀⠀⠀⢀⠄⠒⠉⢀⠔⠁⠀⣧⢞⠮⠭⠵⡀
    ⠀⠀⠘⠒⠉⣾⣀⣀⠀⣀⣀⠦⠗⠹⠙⠃⠁⠀⡠⠔⡡⠔⠒⠉⡨⢴⢹⣿⣏⡆
    ⠀⠀⠀⠀⡸⠉⠀⠀⠁⠀⠀⠀⠀⣇⡠⡄⡶⠯⠔⠈⠀⠀⡠⠊⠀⠀⡿⣿⣿⡇
    ⠀⠀⠀⢀⠇⠀⠀⠀⠀⢀⣀⠤⡤⠵⠊⢸⠀⡠⠤⠤⠐⠉⠀⠀⠀⠀⣷⣿⢿⡇
    ⠀⠀⢀⠃⠀⢀⣀⣀⣀⣠⣀⣀⣿⠉⠉⠉⠉⠀⠀

     

    강사님 코드

    # - 파일명은 클래스가 받아서 처리
    class FileLineIterator :
        def __init__(self, file_path) :
            self.file_path = file_path
            self.file = open(file_path, "r", encoding="utf-8")
    
        def __iter__(self) :
            return self
    
        def __next__(self) :
            print("#1 ---------------")
            ### readline() 파일 정보중에 줄 하나를 가지고온다.
            # - 최초 이후부터는 다음 줄이 있는지 자동으로 체크 후 가지고 온다.
            # - 다음 줄이 없으면 안 가져온다.
            line = self.file.readline()
            
            print(f"#2 : line = {line}")
            
            if line :
                print(f"#3 : line = {line}")
                return line.strip()
            else :
                print("#4 : 이터레이터 종료 ...")
                self.file.close()
                raise StopIteration
    
    ### 이터레이터 클래스 생성하기
    file_path = "./04_example.txt"
    file_iter = FileLineIterator(file_path)
    ### 반복해서 파일 내용 한줄씩 출력하기
    for line in file_iter:
        print(line)
    #1 ---------------
    #2 : line =  이 기상과 이 맘으로 충성을 다하여
    
    #3 : line =  이 기상과 이 맘으로 충성을 다하여
    
    이 기상과 이 맘으로 충성을 다하여
    #1 ---------------
    #2 : line = 괴로우나 즐거우나 나라 사랑하세
    
    #3 : line = 괴로우나 즐거우나 나라 사랑하세
    
    괴로우나 즐거우나 나라 사랑하세
    #1 ---------------
    #2 : line = 무궁화 삼천리 화려 강산
    
    #3 : line = 무궁화 삼천리 화려 강산
    
    무궁화 삼천리 화려 강산
    #1 ---------------
    #2 : line = 대한 사람 대한으로 길이 보전하세
    #3 : line = 대한 사람 대한으로 길이 보전하세
    대한 사람 대한으로 길이 보전하세
    #1 ---------------
    #2 : line = 
    #4 : 이터레이터 종료 ...

     

    ------------------------------------------------------------- 제너레이터 ----------------------------------------------------------------------------------

    <제너레이터 (Generator)>
    함수를 이용해서 이터레이터(반복)의 기능을 구현
    이터레이터와 동일하게 호출 시점에만 메모리를 사용하고 사용이 끝나면 소멸됩니다.
    반환할 때 사용하는 명령어는 return이 아닌, yield를 사용합니다.
    이터레이터와 동일하게 전체 또는 next() 한건씩 출력 가능합니다.

    <예제> 제너레이터 기본 문법

    def simple_generator() :
        ### 첫번째 반환할 값
        yield 1
        
        ### 두번째 반환할 값
        yield 2
        
        ### 세번째 반환할 값
        yield 3
    ### 제너레이터 전체 출력하기
    # - 제너레이터에서는 함수를 객체로 인지하고 사용합니다.
    # - 함수를 생성한다는 의미 또는 제너레이터 객체를 생성한다는 의미를 사용합니다.
    
    for v in simple_generator() :
        print(v)
    1
    2
    3

    <예제> 1부터 5까지의 숫자를 생성해서 반환하는 제너레이터 만들기

    def number_generator() :
        for i in range(1, 6, 1) :
            yield i
    ### 전체 출력하기
    ### - 함수 객체 생성하기
    gen = number_generator()
    for num in gen :
        print(num)
    1
    2
    3
    4
    5
    ### - 함수 객체 생성하기
    gen = number_generator()
    
    ### 한건씩 출력하기
    try :
        print(next(gen))
        print(next(gen))
        print(next(gen))
        print(next(gen))
        print(next(gen))
        print(next(gen))
    except :
        pass
    1
    2
    3
    4
    5
    <예제> 파일 한줄씩 일겅서 반환하는 제너레이터 만들기
    ### read_lines 함수 생성
    def read_lines(file_path) :
        ### 파일처리 시 이터레이터와 다르게, with문을 사용해도 됩니다.
        with open(file_path, "r", encoding = "utf-8") as file :
            for line in file :
                yield line.strip()
    
    ### 제너레이터 함수 생성하기
    gen = read_lines("./04_example.txt")
    for line in gen :
        print(line)
    이 기상과 이 맘으로 충성을 다하여
    괴로우나 즐거우나 나라 사랑하세
    무궁화 삼천리 화려 강산
    대한 사람 대한으로 길이 보전하세
    
     

    ------------------------------------------------------------- 정규표현식 ---------------------------------------------------------------------------------

    """
    <정규표현식 패턴>
    * 대괄호 ([]) : 대괄호 안에 있는 문자 중에 하나라도 매치되면 추출
    * 점 (.) : 앞뒤 문자 사이에 보통 주로 사용함. 하나으 ㅣ문자를 의미함
             : 예시 -> a.c의 패턴인 경우 "abc", adc" .........
    * 반복(*) : 앞의 문자가 0번 이상 반복될 때 추출
              : 예시 -> ab*c의 패턴인 경우 "ac","abc", "abbc", "abbbbbbbbc" ...
    * 반복 (+) : 앞의 문자가 1번 이상 반복될 때 추출
               : 예시 -> ab+b의 패턴인 경우 "abc", "abbc", "abbbbbbbc" .........
    * 반복 ({m, n}) : 앞의 문자가 최소 m번, 최대 n번 반복될 때 추출됨
                    : 예시 -> a{2,4}의 패턴인 경우 "aa", "aaa", "aaaa"
    *반복 (^)과 끝($) : 각 문자열의 시작과 끝을 나타냄
                     : 예시 -> ^abc의 팬턴인 경우 "abc"로 시작하는 문자열에 대해 추출
                     : 예시 -> abc$의 패턴인 경우 "abc"로 끝나는 문자열에 대해 추출
    * 물음표(?) : 바로 앞의 문자가 0또는 1회 나타날 수 있음을 의미함
                : 예시 -> a?의 패턴인 경우 "a"Ehsms ""일 경우 추출함
    * 역슬래시(\) = 이스케이프라고 읽습니다. : 특수문자를 일반 문자로 인식하게 함
    * 소괄호 () = 그룹화라고 읽습니다. : 괄호 안의 패턴을 하나로 그룹으로 묶어서 처리가능
               : 예시 (abc)+ 의 패턴인 경우 "abc", "abcabc", "abcabcabc"....
    * [0-9] : 0에서 9까지의 숫자중 하나
    * [!@#$%^&*(),.?";{}|<>] 특수 기호 중 하나
    * [ㄱ-ㅎㅏ-ㅣ가-힣] : 한글 중 하나
    * [a-zA-Z] : 알파벳 소문자 또는 대문자 중 하나
    
    * \d : 숫자 중 하나
    * \b : 단어의 경계를 나타냄(보통 문장의 처음과 끝에 제시함)
    --> 위의 패턴은 조합해서 사용 가능
    """

     

    <예제> 특정 문자 추출하기

    ### "abcdefg" 문자열에서 ade 문자에 대한 문자만 추출하기
    text = "abcdefg"
    
    ### 추출할 패턴 정의하기
    pattern = re.compile(r"[ade]")
    
    ### text 문자열에서 패턴에 맞는 값만 추출하기
    # - findall : 임의 문자열에서 패턴에 맞는 값을 모두 찾아서 리스트 타입으로 반환합니다.
    rs_text = pattern.findall(text)
    print(rs_text)
    ['a', 'd', 'e']

    <예제> 점(.) 패턴을 이용하기

    text = "abcdef afceeeeazc"
    pattern = re.compile(r"a.c")
    rs_text = pattern.findall(text)
    print(rs_text)
    ['abc', 'afc', 'azc']

     

    728x90
    반응형
Designed by Tistory.