초보 개발자
26강 스페셜 메소드 본문
[스페셜 메소드]
다음과 같은 형태의 이름을 가지면서 파이썬에 의해 호출되는(프로그래머가 그 이름을 직접 명시하여 호출하지 않는) 메소드를 가리켜 '스페셜 메소드'라 한다.
__name__
가장 대표적인 스페셜 메소드로 __init__이 있다. 이는 객체 생성시 자동으로 호출되는 메소드이다.
그리고 다음은 우리가 호출해본 경험이 있는 스페셜 메소드들이다.
__len__ : len 함수가 호출되었을 때 호출 됨
__iter__ : iter 함수가 호출되었을 때 호출 됨
__str__ : str 함수가 호출되었을 때 호출 됨
우리가 iter(s)를 호출하면 실제로 파이썬은 s.__iter__() 이렇게 호출을 한다.
약속이다.
len(s) -> s.__len__()
str(s) -> s.__str__()
위와같이 사용해도 상관은 없다. 하지만 굳이..?
[클래스에 스페셜 메소드 정의하기]
class Car:
def __init__(self,id):
self.id = id
def __len__(self):
return len(self.id)
def __str__(self):
return 'Vehicle number: ' + self.id
def main():
c = Car('12가1234')
print(len(c)) # c.__len__() 호출 -> len(self.id) -> self.id__len__() 호출 7 반환
print(str(c)) # c.__str__() 호출 -> 'Vihecle number : 12가 1234반환'
main()
이렇게 클래스 안에 스페셜 메소드를 정의해주면 기존 스페셜메소드의 오버라이딩이 되어진다.
만약
def __str__(self):
return '안녕하세요'
라고 적는다면 이제 str(c)는 c.__str__()를 호출하는데 우리는 __str__을 안녕하세요 라고 return값을 바꾸었으니 이제 안녕하세요라고만 출력이 되는 것이다.
__len__은 다른건 잘 안됨)
[iterable 객체가 되게끔 하기]
iter함수의 인자로 전달이 가능한 객체를 가리켜 iterable객체라고 한다. iter은 iterator 객체를 반환해야한다.
next함수의 인자로 전달이 가능한 객체를 가리켜 iterator객체라고 한다.
즉
iterable 객체의 조건 : 스페셜 메소드인 __iter__가 존재해야 한다.
iterator 객체의 조건 : 스페셜 메소드인 __next__가 존재해야 한다.
class Car:
def __init__(self,id):
self.id = id
def __iter__(self):
return iter(self.id) # 변수 id의 iterator 객체를 반환
#self.id__iter__() 로 이어지고 이걸 반환
def main():
c = Car('12가1234')
for i in c: # Car객체가 iterable 객체라는 증거
print(i, end = ' ')
main()
1 2 가 1 2 3 4
위의 메소드가 반환하는 iterator 객체는 self.id의 iterator객체이다. 따라서 매우 간단한 구현이라 할 수 있다.
그래도 이로 인해서 __iter__메소드는 iteratro객체를 반환해야한다. 는 조건을 만족시켰다.
때문에 car객체는 iterable객체이다. 이는 car객체를 대상으로 for 루프를 구성할 수 있다는 사실로도 확인할 수 있다.
car클래스는 __iter__라는 메소드를 가지고 있다. iterator객체를 반환하는 역할을 한다.
따라서 car클래스는 iterable객체이다. iter안에 들어갈 수 있기 때문에..
누군가 iter( c(car클래스의 객체)) 를 했을 때 c.__iter__()를 할 테고, 그럼 iter(self.id)가 호출이되고 id의 값은 문자열이니까 iterable객체이므로 self.id.__iter.__() 을 사용하여 iterator객체를 반환하기 때문이다.
만약에 class안에 __iter__을 선언해주지 않았다면 일반 클래스의 객체가 됨으로 for 루프에 넣는다는건 상상도 못할일이다. for 루프로 사용할 수 있는 이유는 iter메서드를 선언해주었기 때문이다.
[iterator 객체가 되게끔 하기]
iterator 객체가 되게끔 하려면 __next__메소드를 가지고 있으면 된다.
그리고 실제 itrerator 객체로 사용할 수 있는 수준으로 메소드가 정의되어야 한다.
조건 1, 가지고 있는 값을 하나씩 반환한다.
조건 2, 더이상 반환할 값이 없는 경우 StopIteration 예외를 발생시킨다.
class Coll:
def __init__(self,d):
self.ds = d
self.cc = 0
def __next__(self):
if len(self.ds) <= self.cc:
raise StopIteration
self.cc += 1
return self.ds[self.cc - 1]
이렇게 구현할 수 있다. 비록 iter함수 호출이 아닌 방법으로 생성이 되었지만
이는 iterator 객체에 해당이 된다. next함수의 인자로 전달이 되어 저장된 값을 하나씩 반환할 뿐 아니라
더이상 반환할 값이 없으면 StropIteration예외도 발생 시키기 때문이다.
[iterator 객체이자 iterable 객체가 되게끔 하기]
class Coll:
def __init__(self,d):
self.ds = d
def __next__(self):
if len(self.ds) <= self.cc:
raise StopIteration
self.cc += 1
return self.ds[self.cc - 1]
def __iter__(self)
self.cc = 0
return self
앞서 배운 것들을 하나로 묶으면 이렇게 표현할 수 있다.
c = coll([1,2,3,4])이렇게 처음 생성해두면
self.ds에 [1,2,3,4]가 들어있을 것이고
for i in c 를하면
for루프가 iter(c)를 할텐데 그럼 c.__iter__()이 실행이되고 cc에 는 0이 초기화, 그리고 자기 자신(ds,cc, __next__,__iter__을 가지고 있는 자신의 객체)을 반환한다. 그리고 이제 for가 next를 통해서 iter(c)를 next를 돌리는 형식이다.
즉 coll 객체는 그 자체로 __next__ 메소드를 갖는 iterator객체이다. 즉 Coll 객체는 __next__메소드를 iterator객체이자. 동시에 __iter__메소드를 갖는 iterable 객체이다. 그래서 coll의 __iter__ 메소드는 self를 반환한다.
사이사이 print문을 넣어서 확인해보자
이렇게 잘 나타나는 걸 확인할 수 있다.
'Python > 윤성우 열혈 파이썬' 카테고리의 다른 글
28강 정보은닉과 __dict__ (0) | 2022.01.24 |
---|---|
27강 연산자 오버로딩 (0) | 2022.01.24 |
24강 상속 (0) | 2022.01.18 |
23강 클래스와 객체의 본질 (0) | 2022.01.18 |
22강 메소드 기반 문자열 조합 (0) | 2022.01.17 |