클래스를 반복 가능하게 만들지 만 클래스를 수정하면 반복자를 수정하지 않는 방법은 무엇입니까?

이프 윌리 고페

저는 파이썬과 일반적으로 코딩을 처음 접했기 때문에 매우 길을 잃었습니다. 이진 검색 트리와 insert () 및 elements ()와 같은 두 가지 메서드를 인스턴스화하는 "Node"클래스 (맨 아래에 표시됨)를 코딩했습니다 (트리를 순서대로 가로 질러 요소 목록을 반환). . 이 클래스를 반복 가능하게 만들어야합니다. "iter __ (self)는 정렬 된 순서로 트리에서 요소를 반환하는 NodeIterator를 반환해야합니다. 트리를 수정해도 기존 반복자를 수정해서는 안됩니다." 지금이 코드를 클래스에 삽입하여이 작업을 수행하려고합니다.

 def __iter__(self):
    x=self.copy()
    x.i=0
    return x

def next(self):
    lst=x.elements()
    #??? No idea what to do from here.  

x = self.copy ()를 정의하여 트리를 수정해도 반복자를 수정해서는 안된다는 사실을 다루려고했지만 이것이 올바른 생각인지 모르겠습니다. 다음은 내 메서드 중 하나에서 사용되는 데코레이터가있는 Node 클래스입니다.

def depth(old_f):
''' Write a decorator that overrides the standard behavior of
a function that returns True or False and instead returns
0 for False or n for number of recursive calls needed to
return True.
'''
    def new_f(*args):
        res = old_f(*args)
        if res is True:
            return 1
        elif res:
            return 1 + res
        else:
            return 0
    return new_f


Class Node(object):
'''
Modify your Node class from homework 4 as follows:

Two elements that compare equal shouldn't be allowed in the Tree. If a
copy is inserted, throw an AlreadyExistsException with the error
message "Element [x] is already in the tree".

__iter__(self) should return a NodeIterator, which returns elements from
the tree in sorted order. Modifying the tree should not modify
existing iterators.
'''
count = 0

def __init__(self, val, left=None, right=None):
    self.Val = val
    self.Left = left
    self.Right = right
    Node.count += 1

def __repr__(self):
    '''If the node has neither a left nor right child,
    simply return Node(val). Else, return Node(x, val, y),
    where x and y are recursive calls that return the
    left and right children, respectively.
    '''
    if self.Left is None and self.Right is None:
        return "Node({})".format(self.Val)
    else:
        return "Node({}, {}, {})".format(self.Left, self.Val, self.Right)

@depth
def search(self, element):
    ''' Finds whether a given element is in the tree.
    Returns True if the element is found, else returns False.

    Give it the depth decorator you defined earlier.
    '''
    if element == self.Val:
        return True
    elif self.Val > element and self.Left is not None:
        return self.Left.search(element)
    elif self.Val < element and self.Right is not None:
        return self.Right.search(element)
    else:
        return False

def insert(self, element):
    ''' Insert an element into a binary search tree rooted
    at this Node. After insertion, return the modified node.

    Our implementation will allow duplicate nodes. The left subtree
    should contain all elements <= to the current element, and the
    right subtree will contain all elements > the current element.
    '''
    if element <= self.Val:
        if self.Left is not None:
            self.Left.insert(element)
        else:
            self.Left = Node(element)
    else:
        if self.Right is not None:
            self.Right.insert(element)
        else:
            self.Right = Node(element)
    return self

def elements(self):
    ''' Return a list of the elements visited in an inorder traversal:
    http://en.wikipedia.org/wiki/Tree_traversal
    Note that this should be the sorted order if you've inserted all
    elements using your previously defined insert function.
    '''
    if self.Left is None and self.Right is None:
        return [self.Val]
    elif self.Left is None and self.Right is not None:
        return [self.Val] + self.Right.elements()
    elif self.Left is not None and self.Right is None:
        return self.Left.elements() + [self.Val]
    else:
        return self.Left.elements() + [self.Val] + self.Right.elements()
ShadowRanger

next수업에서 정의하지 마십시오 . 그것은 당신이 원하는 것이 iterator 가 아닌 iterable 을 가질 때 인스턴스 반복자를 (반드시 객체를 직접 반복해야 함) 만듭니다 . 이를 위해 객체 복사본에 대해 완전히 새로운 반복자 를 정의 하고 반환하도록합니다.__iter__

elements을 효과적으로 스냅 샷 하는 메서드 가 이미 있으므로 Node스냅 샷 반복기를 만드는 데 사용하는 것이 어렵지 않습니다. 어쨌든 순서대로 반복 elements하고 작업을 수행 할 수 있기 때문에 구조를 복사 할 필요가 없습니다 (그리고 부팅 할 때 스냅 샷에서 메모리를 적게 사용함). 일반적으로 저는 __iter__생성기 함수를 만들 것입니다 . 예 :

 def __iter__(self):
     # Python 3 simple version
     yield from self.elements()
     # Python 2 or 3 version
     for x in self.elements():
         yield x

그러나 당신의 과제는 특별한 NodeIterator수업을 필요로하기 때문에 그렇게하지 않을 것입니다. 이를 위해 새 클래스를 만들어야합니다 (기존 Node클래스 내에서 네임 스페이스로 정의 할 수 있음).

class Node(object):
    ...
    class NodeIterator(object):
        def __init__(self, node):
            self.it = iter(node.elements())

        def __iter__(self):
            return self

        def next(self):
            return next(self.it)
        __next__ = next  # Makes code work on Py2 and Py3 without modification

    def __iter__(self):
        return NodeIterator(self)

__iter__( yield마법을 사용하는 함수)에 대한 제너레이터 함수 가 훨씬 더 간단 할 때 왜 내가 특수 클래스를 사용하지 않는지 알 수 있지만 이것이 기본 구조입니다. 반복자에 대한 자세한 내용은 Python wiki 또는 Python collectionsABC 문서 에서 기본 인터페이스 대해 읽을 수 있습니다 .

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관