Итераторы Python – как динамично присвоить self.next в модернизированном классе?

Вы никогда не должны насильственно уничтожать поток, не сотрудничая с ним.

Уничтожение потока удаляет любые гарантии, что блоки попытки/наконец настраивали, таким образом, Вы могли бы оставить блокировки заблокированными, файлы открытый, и т.д.

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

12
задан ollyc 20 July 2009 в 11:06
поделиться

3 ответа

То, что вы пытаетесь сделать, имеет смысл, но здесь что-то злобное творится внутри Python.

class foo(object):
    c = 0
    def __init__(self):
        self.next = self.next2

    def __iter__(self):
        return self

    def next(self):
        if self.c == 5: raise StopIteration
        self.c += 1
        return 1

    def next2(self):
        if self.c == 5: raise StopIteration
        self.c += 1
        return 2

it = iter(foo())
# Outputs: <bound method foo.next2 of <__main__.foo object at 0xb7d5030c>>
print it.next
# 2
print it.next()
# 1?!
for x in it:
    print x

foo () - итератор, который изменяет свой следующий метод на лету - идеально законно где-либо еще в Python. Итератор, который мы создаем, имеет ожидаемый нами метод: it.next is next2. Когда мы используем итератор напрямую, вызывая next (), мы получаем 2. Тем не менее, когда мы используем его в цикле for, мы получаем исходный next, который мы явно перезаписали.

Я не знаком с Внутреннее устройство Python, но похоже, что метод "next" объекта кэшируется в tp_iternext ( http://docs.python.org/c-api/typeobj.html#tp_iternext ), а затем он не обновляется при изменении класса.

Это определенно ошибка Python. Возможно, это описано в PEP генератора, но это '

9
ответ дан 2 December 2019 в 07:03
поделиться

Просто верните итератор. Для этого нужен __ iter __ . Нет смысла пытаться исправить объект, чтобы он находился в итераторе, и вернуть его, когда у вас уже есть итератор.

РЕДАКТИРОВАТЬ: Теперь с двумя методами. Однажды обезьяна исправляет обернутый итератор, второй - оборачивает итератор.

class IteratorWrapperMonkey(object):

    def __init__(self, otheriter):
        self.otheriter = otheriter
        self.otheriter.close = self.close

    def close(self):
        print "Closed!"

    def __iter__(self):
        return self.otheriter

class IteratorWrapperKitten(object):

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

    def __iter__(self):
        return self

    def next(self):
        return self.otheriter.next()

    def close(self):
        print "Closed!"

class PatchableIterator(object):

    def __init__(self, inp):
        self.iter = iter(inp)

    def next(self):
        return self.iter.next()

    def __iter__(self):
        return self

if __name__ == "__main__":
    monkey = IteratorWrapperMonkey(PatchableIterator([1, 2, 3]))
    for i in monkey:
        print i
    monkey.close()

    kitten = IteratorWrapperKitten(iter([1, 2, 3]))
    for i in kitten:
        print i
    kitten.close()

Оба метода работают как с классами нового, так и с классами старого стиля.

3
ответ дан 2 December 2019 в 07:03
поделиться

Похоже на встроенный iter не проверяет next , вызываемый в экземпляре, но в классе, а IteratorWrapper2 не имеет никакого next . Ниже приведена более простая версия вашей проблемы

class IteratorWrapper2(object):

    def __init__(self, otheriter):
        self.next = otheriter.next

    def __iter__(self):
        return self

it=iter([1, 2, 3])
myit = IteratorWrapper2(it)

IteratorWrapper2.next # fails that is why iter(myit) fails
iter(myit) # fails

, поэтому решением было бы вернуть otheriter в __ iter __

class IteratorWrapper2(object):

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

    def __iter__(self):
        return self.otheriter

или написать свой собственный next , заключив внутренний итератор

class IteratorWrapper2(object):

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

    def next(self):
        return self.otheriter.next()

    def __iter__(self):
        return self

Хотя я не понимаю, почему iter просто не использует self.next экземпляра.

4
ответ дан 2 December 2019 в 07:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: