이터러블(iterable)
이터러블은 순회(반복) 가능한 객체를 말한다.
즉, 가지고 있는 원소들을 한 번에 하나씩 돌려줄 수 있는 객체이다.
이터러블은 순회를 "당한다"고 이해하면 좋다.
리스트, 튜플, 문자열, 딕셔너리, 집합, range 등이 이터러블에 해당한다.
가장 간단하게는 for 문에 들어갈 수 있는 객체라고 이해하면 좋다
또한 이터러블은 "__iter__() 라는 메서드를 이용하여 이터레이터를 생성할 수 있는 객체" 로 정의된다.
__iter__() 는 이터러블의 이터레이터를 생성할 수 있는 함수이다.
이터레이터(iterator)
이터레이터는 이터러블의 순회를 주관하는 객체이다.
(이터러블은 순회를 '당하는' 것이고, 이터레이터가 순회를 '행하는' 개념이다.)
이터레이터는 이터러블에서 값을 하나씩 가져오는 객체이다.
이터레이터는 이터러블 객체로부터 값을 순차적으로 가져올 수 있게 해주며,
이 과정에서 이터레이터의 메소드 __iter__()와 __next__()를 사용하는데,
이 두 메소드를 가지는 것을 이터레이터 라고 정의한다.
앞서 __iter__()는 이터레이터를 생성하는 함수라고 하였다.
이터러블에서 __iter__() 메서드를 호출하면 이터레이터인 자기 자신이 반환된다.
또한 이터레이터는 이터러블을 순회하기 때문에, 한 원소에 접근했으면 그 다음 원소로 넘어가야 하는데, 이를 수행해주는 것이 __next__() 메서드이다.
__next__() 를 사용하여 현재 접근한 원소를 반환하고, 다음 원소로 이동할 수 있다.
모든 원소를 순회하고 나면 'StopIteration'이라는 에러가 발생하며 순회가 종료되게 된다.
((-> 이터레이터는 다른 문자열이나 리스트같이 특정 값을 가지는 객체가 아니라, '순회'라는 역할을 수행하는 객체이다.
'순회' 라는 역할을 하는 새로운 개념의 객체라고 생각하는게 편하다.
이터레이터는 순회하면서 이터러블의 요소를 보여줄 뿐인거지, 그 요소의 값을 직접 가지는 건 아니라는 것))
-> 참조하면서 상태 유지임. 수정하기.
__iter__() 메서드:
__iter__() 메서드는 이터러블 객체에서 호출된다.
이 메서드는 이터레이터 객체를 생성하고 반환한다.
이터러블 객체의 __iter__() 메서드를 호출하면 해당 이터러블에 대한 이터레이터 객체가 생성되며,
이터레이터에서의 __iter__()은 자기 자신을 반환한다.
__next__() 메서드:
__next__() 메서드는 이터레이터 객체에서 호출된다.
(이터레이터는 __iter__()와 _next__() 메소드를 가지고 있어야만 한다.)
이 메서드는 다음 값을 반환하고, 이터레이터의 내부 상태를 업데이트한다.(현재 원소를 반환했으면 다음 원소로 넘어감)
이터레이터 객체는 __next__() 메서드를 사용하여 현재 접근한 원소를 반환하고 다음 원소로 이동한다.
모든 원소를 순회하고 나면 StopIteration 예외가 발생하며 순회가 종료된다.
이터러블을 1바퀴 다 돌았으면 더이상 해당 이터레이터로 __next__()를 이용하며 순회할 수 없다.
더 돌고 싶으면 새로운 이터레이터를 생성해야 한다.
=> 여기서 알 수 있듯이, __iter__()메소드를 가지는 것은 이터러블이다. 그런데 이터레이터도 __iter__()를 가진다.
따라서 이터레이터는 항상 이터러블이라고 정의할 수 있다.
여기서 들었던 의문점
-> 이터레이터 자기 자신을 나타낼뿐인 __iter__()는 이터레이터에 왜 필요한가?
= 이터레이터는 이터러블 객체를 반복하여 순회해야 하기 때문에, 자기 자신도 이터러블처럼 동작할 수 있어야 한다.
그렇기에 이터레이터는 __iter__() 메서드를 가짐으로써 이터러블로 정의 내려질 수 있어야 한다.
(__iter__() 메서드를 구현하여 이터러블로도 정의된다.)
(앞서 말한, 이터러블 : 순회 가능한 객체)
- "<list_iterator object at 0x7de5aee5c520>"는 이터레이터 객체의 표현입니다. 이 값은 메모리 주소를 나타내며, 새로운 이터레이터를 생성할 때마다 변경됩니다. 이는 파이썬 내부에서 이터레이터 객체를 구분하기 위한 고유한 식별자입니다.
<list_iterator object at 0x7de5aee5c520>"는 이터레이터 객체의 식별자를 나타내는 값입니다.
-> id()와 출력 형태가 다른 것은 10진수와 16진수 차이.
이터레이터는 그냥 그대로 출력하면 이터레이터 객체의 메모리 주소(식별자)를 반환하므로, 우리가 원하는 값을 볼 수 없다.
원하는 값을 반환하기 위해서는 앞서 말했듯이 __next__()메서드를 써주면 된다.
하지만 next함수가 아닌 for문, list(), tuple(), dict() 등의 함수에 넣어주어도 이터레이터의 값이 반환되는 것을 볼 수 있다.
그 이유는 이들 함수 내부에 모두 이터레이터 역할이 존재하기 때문이다.
(이터레이터는 이터러블이라 하고 여기서 이터러블은 또 이터레이터라고 하면서 둘은 다르다고 하니까 짜증이 난다.)
분명 시작하면서 저들은 이터러블이라고 하였다.
하지만 여기서 '이터레이터' 가 존재 한다는 것은 이 이터러블한 객체의 '함수'를 말한다.
예를 들어
my_list = [1,2,3,4]
-> 여기서 my_list는 리스트라는 객체이다. 이 my_list는 이터러블이지만 이터레이터는 아니다.
tuple1 = (1,2)
list(tuple1)
-> 여기서 사용된 list()는 함수이다. 이 list()함수가 내부적으로 이터레이터를 생성할 수 있다.
이 생성된 이터레이터를 사용하여 주어진 이터러블 객체의 요소들에 접근한다. 이터레이터가 있으니 __next___() 메서드도 내부에 존재하고 다음 값을 반환하여서 리스트로 변환한다.
list()함수나 tuple() 함수 등은 인자로 이터러블을 받는데, 이터레이터는 이터러블이기 때문에, 이터레이터 결과를 해당 함수에 넣어주어도 원하는 결과 값이 반환되는 것이다.
[파이썬] iterable과 iterator 의 차이가 뭐예요?
"뭐에요? 🤨" 시리즈 1편 평소에 헷갈렸던 것들이나 암기해두면 좋을 것들, 대강 알고 정확한 정의를 몰랐던 것들을 좀 깊게 들어가보면서 쭉 질문별, 문제상황별로 포스트를 작성해보겠다.
velog.io
'파이썬' 카테고리의 다른 글
[Pandas] 기본 함수 정리 (0) | 2024.08.16 |
---|---|
[Python] 참조(Reference) + 복사(Copy) (0) | 2024.07.05 |
map()함수 (0) | 2024.06.09 |
lambda()함수 (0) | 2024.06.09 |
리스트 컴프리헨션(list comprehension) (0) | 2024.06.09 |