2015-02-22 3 views
2

У меня есть класс, который выглядит следующим образомРеализация __next__ в пользовательском классе

Class myClass: 

    def __init__(self, key, value): 
     self.key = key 
     self.value = value 

где key является строкой и value всегда список элементов MyClass, возможно, пустые.

Я хочу определить свой собственный метод iter, который возвращает value.key для каждого value в values. Я попробовал

def __iter__(self): 
    return self 

def __next__(self): 
    try: 
     self.value.next().key 
    except: 
     raise StopIteration 

но это зацикливание навсегда. Что я делаю не так? Кроме того, если я хочу иметь Python совместимости 2/3, я должен добавить метод

def next(self): 
    return self.__next__() 
+1

Не должно быть 'def __iter __ (self): return iter (self.value)'? – jonrsharpe

+0

насколько совместимость идет да, вы также можете просто использовать 'next (self ..)'. Что именно вы хотите сделать? Что означает 'self.value.next(). Key' должен делать? –

+0

@jonrsharpe Это была моя первая попытка, но тогда я потеряю возможность определить свой собственный '__next__', который мне нужен, чтобы извлечь« ключ »из значений – meto

ответ

3

Нет причин для внедрения __next__. Вы можете использовать __iter__, чтобы вернуть генератор, который будет делать то, что вы хотите.

class Pair(object): 

    def __init__(self, key, value): 
     self.key = key 
     self.value = value 

    def __iter__(self): 
     return (v.key for v in self.value) 

    # alternative iter function, that allows more complicated logic 
    def __iter__(self): 
     for v in self.value: 
      yield v.key 

p = Pair("parent", [Pair("child0", "value0"), Pair("child1", "value1")]) 

assert list(p) == ["child0", "child1"] 

Этот способ делать вещи совместим с python2 и Python3 как возвращенного генератора будет иметь требуемую next функцию в python2 и __next__ в Python3.

2

вам нужно извлечь и сохранить в итератор в списке self.value - вы не можете просто позвонить next в списке , вам нужен итератор в таком списке.

Итак, вам нужен вспомогательный класс итератора:

class myClassIter(object): 

    def __init__(self, theiter): 
     self.theiter = theiter 

    def __next__(self): 
     return next(self.theiter).key 

    next = __next__ 

который я также сделал Py 2/3 совместит с object базы и соответствующей ступенчатостью.

Здесь я предполагаю, что каждый элемент в списке имеет атрибут key (поэтому единственным ожидаемым исключением является StopIteration, которое вы можете просто размножать). Если это не так, и вы хотите просто прекратить итерацию, когда предмет встречается без атрибута, необходимы try/except, но держите его в напряжении! - важный аспект дизайна обработки исключений. То есть, если они действительно ваши данные:

def __next__(self): 
     try: return next(self.theiter).key 
     except AttributeError: raise StopIteration 

не поймать все исключения - только те, которые вы специально ожидали!

Теперь в myClass, вы хотите:

def __iter__(self): 
    return myClassIter(iter(self.value)) 

Это означает, что myClass является итерацию, не итератора, так что вы можете, например, правильно иметь более чем одну петлю на myClass пример:

mc = myClass(somekey, funkylist) 
for ka in mc: 
    for kb in mc: 
     whatever(ka, kb) 

Если mc сама итератора, внутренний цикл будет исчерпывает его и семантика п поэтому петли были бы совершенно разными.

Если вы действительно хотите, такие совершенно разные семантику (то есть вы хотитеmc быть сам итератор, а не только итератор), то вы должны отказаться от дополнительного класса (но все-таки нужно хранить итератор на self.value, как атрибут экземпляра для myClass) - это было бы странно, неудобно, но это - это (едва ли возможно), что это действительно то, что вам нужно ...

Смежные вопросы