Страницы

Поиск по вопросам

пятница, 6 марта 2020 г.

Атрибут __next__ не переопределяется

#python #python_3x #генераторы #динамическая_типизация


У меня есть класс в котором я переопределяю метод __next __ после его первого вызова,
но проблема в том что работать продолжает старый __next __.

class I:
    def __init__(self, head):
        self.head = iter(head)

    def __iter__(self):
        return self

    def __next__(self):
        self.__next__ = self.head.__next__
        return 'a'


i = I((1, 2, 3))
i_it = iter(i)
print(next(i_it)) #выводит 'a'. Все ок
print(next(i_it)) #снова 'a'. Почему не 1?
print(i_it.__next__) #
вроде __next__ переопределен 


P.S Если переопределять что-то другое то все работает:

    def __next__(self):
        self.__next__ = self.head.__next__
        self.x = 1
        return 'a'


После вызова next(self) x будет 1.
Ссылка на онлайн компилятор: https://repl.it/HVOC/17

P.P.S: В коментариях говорят что если вызывать i_it.__next __() то все будет работать
так как надо, я это знаю, но штука в том что в любом итераторе(цикл for например) работает
next(self), а не self.__next __().
    


Ответы

Ответ 1



На сколько я понимаю, в cpython встроенная функция next() определяется тут: builtin_next(). Можно увидеть, что при вызове имеется следующая конструкция: res = (*it->ob_type->tp_iternext)(it); Полагаю, что она равносильна примерно такой конструкции на Python: next(i) --> i.__class__.__next__(i) что сходится с тем, что видно на практике. Как дела происходят в других интерпретаторах мне не известно.

Ответ 2



Сначала i_it.__next__ = i.__next__. Затем i.__next__ = self.head.__next__ Но i_it.__next__ остался прежним, тк его не меняли. Те __next__ был изменен только для объекта класса i, но не для итератора i_it

Комментариев нет:

Отправить комментарий