it-source

컨테이너 객체(Python)에 __iter__(자체)를 구현하는 방법

criticalcode 2023. 7. 20. 21:59
반응형

컨테이너 객체(Python)에 __iter__(자체)를 구현하는 방법

사용자 정의 컨테이너 개체를 작성했습니다.

페이지에 따르면 이 방법을 내 객체에 구현해야 합니다.

__iter__(self)

그러나 Python 참조 매뉴얼의 Iterator Types에 대한 링크를 추적한 결과, 사용자 자신의 유형을 구현하는 방법에 대한 예가 제공되지 않았습니다.

누가 이 방법을 보여주는 스니펫(또는 리소스에 대한 링크)을 게시할 수 있습니까?

제가 쓰고 있는 컨테이너는 지도입니다(즉, 고유한 키로 값을 저장합니다).딕트는 다음과 같이 반복할 수 있습니다.

for k, v in mydict.items()

이 경우 반복기에서 두 개의 요소(튜플?)를 반환할 수 있어야 합니다.이러한 반복기를 구현하는 방법은 여전히 명확하지 않습니다(친절하게 제공된 몇 가지 답변에도 불구하고).누가 지도와 같은 컨테이너 객체에 대한 반복기를 구현하는 방법에 대해 좀 더 설명해 주시겠습니까?(즉, 딕트처럼 작동하는 사용자 지정 클래스)?

저는 보통 발전기 기능을 사용합니다.수율 문을 사용할 때마다 시퀀스에 항목이 추가됩니다.

다음은 5개를 생성하는 반복기를 생성하고 some_list의 모든 항목을 생성합니다.

def __iter__(self):
    yield 5
    yield from some_list

Python 3.3 이전 버전은 존재하지 않았으므로 다음을 수행해야 합니다.

def __iter__(self):
    yield 5
    for x in some_list:
        yield x

다른 옵션은 여기에 문서화된 것처럼 '수집 모듈에서 적절한 추상 기본 클래스를 상속하는 것입니다.

컨테이너가 자체 반복기인 경우 다음에서 상속할 수 있습니다.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: 글렌 메이너드 씨 덕분에 반복기와 반복기가 아닌 반복기의 차이를 명확히 할 필요가 있었습니다.

python의 "iterable interface"는 두 가지 방법으로 구성됩니다.__next__()그리고.__iter__().그__next__함수는 반복자 동작을 정의하기 때문에 가장 중요합니다. 즉, 함수는 다음에 반환해야 할 값을 결정합니다.__iter__()메소드는 반복의 시작점을 재설정하는 데 사용됩니다.종종, 당신은 그것을 발견할 것입니다.__iter__()다음과 같은 경우에는 그냥 자신을 돌아볼 수 있습니다.__init__()시작점을 설정하는 데 사용됩니다.

"itable interface"를 구현하고 임의의 시퀀스 클래스에서 임의의 인스턴스에 대한 반복기를 정의하는 클래스 역을 정의하려면 다음 코드를 참조하십시오.__next__()메서드는 시퀀스의 끝에서 시작하고 시퀀스의 역순으로 값을 반환합니다. interface는 " 퀀스인를이스"를 .__len__() a 리고a.__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__()이미 다음 () 방법(generator▁the 객체)을 정의한 경우에는 자신을 반환합니다.

다음은 발전기의 더미 예입니다.

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

개체에 개체의 반복자를 바인딩할 데이터 집합이 포함된 경우 커닝하여 다음 작업을 수행할 수 있습니다.

>>> 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

매핑에 대한 질문에 답하기: 제공된 정보__iter__매핑 키 위에 반복해야 합니다.다음은 매핑을 만드는 간단한 예입니다.x -> x * xABC 매핑을 확장하는 Python3에서 작동합니다.

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)

경우에 따라 작동할 수 있는 한 가지 옵션은 사용자 정의 클래스를 다음에서 상속하도록 만드는 것입니다.dict만약 이것이 딕트처럼 행동한다면 이것은 논리적인 선택처럼 보입니다. 아마도 딕트여야 할 것입니다.이런 식으로, 당신은 딕트와 같은 반복을 무료로 얻을 수 있습니다.

class MyDict(dict):
    def __init__(self, custom_attribute):
        self.bar = custom_attribute

mydict = MyDict('Some name')
mydict['a'] = 1
mydict['b'] = 2

print mydict.bar
for k, v in mydict.items():
    print k, '=>', v

출력:

Some name
a => 1
b => 2

dict에서, dict를 합니다.iter를 들어, 키 예: 건뛰기키2궁지에 몰렸을 때.

# method 1
class Dict(dict):
    def __iter__(self):
        keys = self.keys()
        for i in keys:
            if i == 2:
                continue
            yield i

# method 2
class Dict(dict):
    def __iter__(self):
        for i in super(Dict, self).__iter__():
            if i == 2:
                continue
            yield i

언급URL : https://stackoverflow.com/questions/4019971/how-to-implement-iter-self-for-a-container-object-python

반응형