클래스에서 init, iter, generator 사용
__init__()
클래스를 정의하면서 인수를 전달할 경우 __init__()메서드를 사용합니다.이 메서드는 클래스에 인수를 전달하는 등 초기화를 위해 적용합니다.
-
class Fib:
- ‘’’iterator that yields numbers in the Fibonacci sequence’’’①
- def __init__(self, maxnum):
- 내용 ②
② __init__() 메소드는 클래스 개체인 인스턴스를 생성하면서 호출됩니다. 즉, 인스턴스 생성시 첫번째로 실행되는 코드입니다.
이 메소드의 인수중 첫번째 인수는 self입니다. 이것은 새롭게 생성된 객체(인스턴스)를 참조하는 것으로 명시적으로 나타내어야 합니다.
초기화자는 단순히 인자 전달 외에 그 인자의 정성적인 측면의 정보를 제공할 수 있습니다.
-
class Fib:
- '''iterator that yields numbers in the Fibonacci sequence'''
- def __init__(self, maxnum):
- if maxnum <0 :
- raise ValueError("maxnum은 양수이어야 합니다.")
- ---------------------------------------------------------------------------
- ValueError Traceback (most recent call last)
- ...
- ---→ 5 raise ValueError("maxnum은 양수이어야 합니다.")
- ValueError: maxnum은 양수이어야 합니다.
Instance
클래스를 정의하자마자 같은 이름으로 새로운 클래스 객체를 생성할 수 있습니다. 이를 클래스 객체 즉, 인스턴스라고 합니다.인스턴스는 다음과 같이 생성할 수 있습니다. 이 경우 인수는 생성자 __init__()에 명시한 인자들과 같습니다. 단, 인스턴스 생성시 self는 암묵적으로 호출되므로 명시하지 않아야 합니다.
객체이름 = 클래스이름(인자들)
-
class Fib:
- '''피보나치 수열을 생성하기 위한 클래스'''
- def __init__(self, maxnum):
- self.maxnum = maxnum
- def re(self):
- mx=self.maxnum
- return (mx)
fib=Fib(10)
print(dir(fib), end=" ")
- ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'maxnum']
- __main__.Fib
- '피보나치 수열을 생성하기 위한 클래스'
- 10
__class__속성은 인스턴스의 위치를 나타내며 __doc__는 클래스의 docstring을 반환합니다.
다음의 __init__()에 정의된 self.maxnum은 인스턴스 변수라고 합니다. 이 메소드에서 선언된 변수는 전역변수로서 인스턴스 내의 모든 메소드에서 사용됩니다. 그러므로 다음 생성한 메소드 re()에서 그 인스턴스 변수를 사용할 수 있습니다.
-
fib.re()
- 10
반복자 (Iterator)
위 클래스내에서 반복자를 생성합니다. 반복자는 클래스 내에서 __iter__() 메소드에 의해 정의됩니다.인스턴스에서 매직메소드인 __iter__()은 자동적으로 for loop를 실행합니다. 그러나 이렇게 실행되는 for loop는 일반적인 반복문의 실행과는 약간의 차이를 가집니다. 즉, 일반적인 반복문의 경우 객체내의 모든 원소들을 생성한 후에 호출의 결과를 반환합니다. 그에 반해 iterator는 객체내의 각 원소가 실행되고 호출된 후 다른 원소가 실행되고 호출됩니다. 즉, 실행과 반환이 한 쌍으로 이루어집니다.
다음과 같이 작성할 수 있습니다.
-
class Fib:
- '''피보나치 수열을 생성하기 위한 클래스'''
- def __init__(self, maxnum): ①
- self.maxnum = maxnum
- def __iter__(self): ②
- self.a=0
- self.b=1
- return(self)
- def __next__(self): ③
- re=self.a
- if re > self.maxnum:
- raise StopIteration
- self.a, self.b=self.b, self.a+self.b
- return(re)
fib=Fib(10)
for i in fib:
- print(i, end=" ")
- 0 1 1 2 3 5 8
대신에 위에서 소개한 것과 같이 인스턴스에서 반복자인 ②에 의해 for loop가 생성되며 ③에 의해 각 원소가 실행됩니다.
실행된 결과 호출을 위해서 yield() 함수를 사용할 수 있지만 이 경우는 __iter__ 대신에 for~loop문을 직접 사용하는 gnerator(생성자)에서만 사용할 수 있습니다. 위의 코드에서와 같이 yield ()대신에 return()을 사용합니다.
__iter__() 메소드에서 if 구문은 인수로 전달한 값보다 클경우 이 과정을 중지시키기 위해 StopIteration 식을 사용하였습니다. 이 식은 예외 발생이 아닌 정상적으로 인스턴스의 실행으로 중지시키는 것입니다.
반복자에 의한 결과의 반환은 위의 for loop 대신에 결과의 자료형을 확정함으로서 보다 직접적인 결과를 반환할 수 있습니다.
반복자나 생성자에 의한 결과는 실행단계에서 결과 객체의 원소들이 저장될 위치만을 확보한 상태로서 반환될 결과의 자료형이나 값이 결정되지 않은 상태입니다. 다시말하면 결과 객체의 각 원소를 호출할 때 참조주소에 위치한 값을 호출하는 것입니다.
이러한 과정을 확장하면 모든 결과 원소들로 구성된 객체의 자료형을 확정함으로서 전체를 반환할 수 있게 됩니다.
-
list(x)
- [0, 1, 1, 2, 3, 5, 8]
발생자(generator)
fibonacci 수열을 생성하기 위해 generator를 사용하는 경우는 보다 간단합니다. 즉, iterator(반복자)인 __iter__() 메서드 대신 반복문을 직접적으로 사용할 수 있으므로 단일한 함수로 작성할 수 있습니다.-
def fibo_gen(maxnum):
- a, b=0, 1
- while a < maxnum:
- yield a
- a, b=b, a+b
(1) 결과를 각 원소단위로 반환하기 위해 next()함수를 사용합니다. 이 경우 생성자가 함수의 형태로 작성된 경우 에도 객체의 모든 원소에 대한 참조를 확정하기 위해 인스턴스를 생성하여 사용합니다. next()를 사용할 경우 지정한 인수의 범위를 초과하면 자동적으로 예외를 발생시킵니다.
-
x=fibo_gen(10)
next(x)
- 0
- 1
- 1
- 2
- 3
- 5
- 8
- StopIteration:
-
for i in fibo_gen(10):
- print(i, end=" ")
- 0 1 1 2 3 5 8
-
list(fibo_gen(10))
- [0, 1, 1, 2, 3, 5, 8]
- (0, 1, 1, 2, 3, 5, 8)
반복자 (Iterator)
위 클래스내에서 반복자를 생성합니다. 반복자는 클래스 내에서 __iter__() 메소드에 의해 정의됩니다.인스턴스에서 매직메소드인 __iter__()은 자동적으로 for loop를 실행합니다. 그러나 이렇게 실행되는 for loop는 일반적인 반복문의 실행과는 약간의 차이를 가집니다. 즉, 일반적인 반복문의 경우 객체내의 모든 원소들을 생성한 후에 호출의 결과를 반환합니다. 그에 반해 iterator는 객체내의 각 원소가 실행되고 호출된 후 다른 원소가 실행되고 호출됩니다. 즉, 실행과 반환이 한 쌍으로 이루어집니다.
다음과 같이 작성할 수 있습니다.
-
class Fib:
- '''피보나치 수열을 생성하기 위한 클래스'''
- def __init__(self, maxnum): ①
- self.maxnum = maxnum
- def __iter__(self): ②
- self.a=0
- self.b=1
- return(self)
- def __next__(self): ③
- re=self.a
- if re > self.maxnum:
- raise StopIteration
- self.a, self.b=self.b, self.a+self.b
- return(re)
fib=Fib(10)
for i in fib:
- print(i, end=" ")
- 0 1 1 2 3 5 8
대신에 위에서 소개한 것과 같이 인스턴스에서 반복자인 ②에 의해 for loop가 생성되며 ③에 의해 각 원소가 실행됩니다.
실행된 결과 호출을 위해서 yield() 함수를 사용할 수 있지만 이 경우는 __iter__ 대신에 for~loop문을 직접 사용하는 gnerator(생성자)에서만 사용할 수 있습니다. 위의 코드에서와 같이 yield ()대신에 return()을 사용합니다.
__iter__() 메소드에서 if 구문은 인수로 전달한 값보다 클경우 이 과정을 중지시키기 위해 StopIteration 식을 사용하였습니다. 이 식은 예외 발생이 아닌 정상적으로 인스턴스의 실행으로 중지시키는 것입니다.
반복자에 의한 결과의 반환은 위의 for loop 대신에 결과의 자료형을 확정함으로서 보다 직접적인 결과를 반환할 수 있습니다.
반복자나 생성자에 의한 결과는 실행단계에서 결과 객체의 원소들이 저장될 위치만을 확보한 상태로서 반환될 결과의 자료형이나 값이 결정되지 않은 상태입니다. 다시말하면 결과 객체의 각 원소를 호출할 때 참조주소에 위치한 값을 호출하는 것입니다.
이러한 과정을 확장하면 모든 결과 원소들로 구성된 객체의 자료형을 확정함으로서 전체를 반환할 수 있게 됩니다.
-
list(x)
- [0, 1, 1, 2, 3, 5, 8]
발생자(generator)
fibonacci 수열을 생성하기 위해 generator를 사용하는 경우는 보다 간단합니다. 즉, iterator(반복자)인 __iter__() 메서드 대신 반복문을 직접적으로 사용할 수 있으므로 단일한 함수로 작성할 수 있습니다.-
def fibo_gen(maxnum):
- a, b=0, 1
- while a < maxnum:
- yield a
- a, b=b, a+b
(1) 결과를 각 원소단위로 반환하기 위해 next()함수를 사용합니다. 이 경우 생성자가 함수의 형태로 작성된 경우 에도 객체의 모든 원소에 대한 참조를 확정하기 위해 인스턴스를 생성하여 사용합니다. next()를 사용할 경우 지정한 인수의 범위를 초과하면 자동적으로 예외를 발생시킵니다.
-
x=fibo_gen(10)
next(x)
- 0
- 1
- 1
- 2
- 3
- 5
- 8
- ---------------------------------------------------------------------------
- StopIteration Traceback (most recent call last)
- ----> 1 next(x)
- StopIteration:
-
for i in fibo_gen(10):
- print(i, end=" ")
- 0 1 1 2 3 5 8
-
list(fibo_gen(10))
- [0, 1, 1, 2, 3, 5, 8]
- (0, 1, 1, 2, 3, 5, 8)
댓글
댓글 쓰기