사용자 지정 컨테이너 개체를 작성했습니다.
이 페이지 에 따르면 내 개체에이 메서드를 구현해야합니다.
__iter__(self)
그러나 Python 참조 설명서의 반복자 유형 에 대한 링크를 따라 가면 직접 구현하는 방법에 대한 예제가 제공되지 않습니다.
누군가가이를 수행하는 방법을 보여주는 스 니펫 (또는 리소스에 대한 링크)을 게시 할 수 있습니까?
내가 쓰고있는 컨테이너는 맵 (즉, 고유 키로 값을 저장)입니다. dicts는 다음과 같이 반복 될 수 있습니다.
for k, v in mydict.items()
이 경우 반복기에서 두 개의 요소 (튜플?)를 반환 할 수 있어야합니다. (친절하게 제공된 여러 답변에도 불구하고) 그러한 반복자를 구현하는 방법은 아직 명확하지 않습니다. 누군가지도와 같은 컨테이너 객체에 대해 반복기를 구현하는 방법에 대해 좀 더 설명해 주시겠습니까? (예 : dict처럼 작동하는 사용자 정의 클래스)?
답변
나는 일반적으로 생성기 함수를 사용합니다. yield 문을 사용할 때마다 시퀀스에 항목이 추가됩니다.
다음은 5를 산출하는 반복자를 생성 한 다음 some_list의 모든 항목을 생성합니다.
def __iter__(self):
yield 5
yield from some_list
3.3 이전 버전 yield from
은 존재하지 않았으므로 다음을 수행해야합니다.
def __iter__(self):
yield 5
for x in some_list:
yield x
답변
또 다른 옵션은 여기에 설명 된대로`collections 모듈에서 적절한 추상 기본 클래스에서 상속하는 것 입니다.
컨테이너가 자체 반복자 인 경우
collections.Iterator
. next
그런 다음 메서드 를 구현하기 만하면됩니다.
예 :
>>> from collections import Iterator
>>> class MyContainer(Iterator):
... def __init__(self, *data):
... self.data = list(data)
... def next(self):
... if not self.data:
... raise StopIteration
... return self.data.pop()
...
...
...
>>> c = MyContainer(1, "two", 3, 4.0)
>>> for i in c:
... print i
...
...
4.0
3
two
1
당신이보고있는 동안 collections
모듈에서 상속 고려 Sequence
, Mapping
즉 더 적합한 지 또는 다른 추상 기본 클래스입니다. 다음은 Sequence
하위 클래스 의 예입니다 .
>>> from collections import Sequence
>>> class MyContainer(Sequence):
... def __init__(self, *data):
... self.data = list(data)
... def __getitem__(self, index):
... return self.data[index]
... def __len__(self):
... return len(self.data)
...
...
...
>>> c = MyContainer(1, "two", 3, 4.0)
>>> for i in c:
... print i
...
...
1
two
3
4.0
NB : 한편으로는 반복기와 다른 한편으로는 반복기보다는 반복 가능한 컨테이너 간의 차이점을 명확히해야한다는 점에주의를 기울여 주신 Glenn Maynard에게 감사드립니다.
답변
일반적으로 __iter__()
next () 메서드 (generator 객체)를 이미 정의한 경우 self를 반환합니다.
다음은 생성기의 더미 예제입니다.
class Test(object):
def __init__(self, data):
self.data = data
def next(self):
if not self.data:
raise StopIteration
return self.data.pop()
def __iter__(self):
return self
다음 __iter__()
과 같이 사용할 수도 있습니다 :
http://mail.python.org/pipermail/tutor/2006-January/044455.html
답변
개체에 개체의 iter를 바인딩하려는 데이터 집합이 포함 된 경우 속임수를 사용하여 다음을 수행 할 수 있습니다.
>>> class foo:
def __init__(self, *params):
self.data = params
def __iter__(self):
if hasattr(self.data[0], "__iter__"):
return self.data[0].__iter__()
return self.data.__iter__()
>>> d=foo(6,7,3,8, "ads", 6)
>>> for i in d:
print i
6
7
3
8
ads
6
답변
파이썬의 “반복 가능한 인터페이스”는 두 가지 메서드 __next__()
와 __iter__()
. 이 __next__
함수는 반복기 동작을 정의하므로 가장 중요합니다. 즉, 함수는 다음에 반환되어야하는 값을 결정합니다. 이 __iter__()
메서드는 반복의 시작점을 재설정하는 데 사용됩니다. 종종 시작점을 설정하는 데 사용 __iter__()
되면 self를 반환 할 수 있습니다 __init__()
.
“반복 가능한 인터페이스”를 구현하고 시퀀스 클래스의 모든 인스턴스에 대해 반복기를 정의하는 리버스 클래스를 정의하려면 다음 코드를 참조하십시오. 이 __next__()
메서드는 시퀀스의 끝에서 시작하여 시퀀스의 역순으로 값을 반환합니다. “시퀀스 인터페이스”를 구현하는 클래스의 인스턴스는 __len__()
및 __getitem__()
메서드를 정의해야합니다 .
class Reverse:
"""Iterator for looping over a sequence backwards."""
def __init__(self, seq):
self.data = seq
self.index = len(seq)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
>>> rev = Reverse('spam')
>>> next(rev) # note no need to call iter()
'm'
>>> nums = Reverse(range(1,10))
>>> next(nums)
9
답변
매핑에 대한 질문에 답하려면 제공된 사용자 가 매핑 키 를 __iter__
반복해야 합니다. 다음은 매핑을 생성 하고 ABC 매핑을 확장하는 Python3에서 작동 하는 간단한 예제입니다 .x -> x * x
import collections.abc
class MyMap(collections.abc.Mapping):
def __init__(self, n):
self.n = n
def __getitem__(self, key): # given a key, return it's value
if 0 <= key < self.n:
return key * key
else:
raise KeyError('Invalid key')
def __iter__(self): # iterate over all keys
for x in range(self.n):
yield x
def __len__(self):
return self.n
m = MyMap(5)
for k, v in m.items():
print(k, '->', v)
# 0 -> 0
# 1 -> 1
# 2 -> 4
# 3 -> 9
# 4 -> 16
답변
dict
다른 사람들이 제안한 것처럼 상속하고 싶지 않은 경우 __iter__
사용자 지정 사전의 원유 예제 를 구현하는 방법에 대한 질문에 대한 직접적인 답변이 있습니다 .
class Attribute:
def __init__(self, key, value):
self.key = key
self.value = value
class Node(collections.Mapping):
def __init__(self):
self.type = ""
self.attrs = [] # List of Attributes
def __iter__(self):
for attr in self.attrs:
yield attr.key
여기에 잘 설명 된 생성기를 사용합니다. .
에서 상속하므로 및 다음을 Mapping
구현해야합니다 .__getitem__
__len__
def __getitem__(self, key):
for attr in self.attrs:
if key == attr.key:
return attr.value
raise KeyError
def __len__(self):
return len(self.attrs)