Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 12, 2015 14:41:16

taxik
Зарегистрирован: 2015-04-12
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Протоколы итерации

# Python 3

Cоздадим список "L", который явл. итерируемым объектом но не итератором, мы не можем к нему применить next(L) или L.__next__()

L = [1,2,3,4,5] 

Теперь создадим итератор для этого списка, здесь мы уже можем применять эти фунции к "I"
I = iter(L)

Если в цикл for передать "I" то он начнет переберать его с помощь __next__(). Вопрос - что он(Python) делает когдя я передаю в for "L“? Он автоматически создает итератор для него, или же он использует что то другое?
Я натыкался на такое выражение ”протокол доступа по индексам", если он существует то с помощью какой функции ведется перебор, если такая функция существует то я могу перебрать его без цыкла for (так же как и итератор списка через __next__())?
Я подмал что может быть, Python не создавая итератор может перебрать список просто от 0 до выброса исключения, но как в таком случае он перебирает словарь?

Отредактировано taxik (Апрель 12, 2015 14:46:30)

Офлайн

#2 Апрель 12, 2015 14:49:06

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10016
Репутация: +  857  -
Профиль   Отправить e-mail  

Протоколы итерации

taxik
Вопрос - что он(Python) делает когдя я передаю в for "L“? Он автоматически создает итератор для него, или же он использует что то другое?
Он вызывает iter() для L и использует полученный объект для вызовов next().



Офлайн

#3 Апрель 12, 2015 14:51:14

taxik
Зарегистрирован: 2015-04-12
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Протоколы итерации

py.user.next
Спасибо, а вы можете дать ссылку где это указано(можно и на англ.)?

А протокол доступа по индексам это просто?
L[0], L[1]...

Отредактировано taxik (Апрель 12, 2015 14:55:54)

Офлайн

#4 Апрель 12, 2015 14:59:56

terabayt
От: Киев
Зарегистрирован: 2011-11-26
Сообщения: 1099
Репутация: +  103  -
Профиль   Отправить e-mail  

Протоколы итерации

не знаю где это указано, но можно на примере увидеть что for автоматически вызывает iter

class C:
    def __init__(self, stop):
        self.current = 0
        self.stop = stop
    def __iter__(self):
        print 'iter!!! ---'
        return self
    def next(self):
        if self.current > self.stop:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1
for c in C(8):
    print c
python 3
class C:
    def __init__(self, stop):
        self.current = 0
        self.stop = stop
    def __iter__(self):
        print('iter!!! ---')
        return self
    def __next__(self):
        if self.current > self.stop:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1
for c in C(8):
    print(c)



————————————————
-*- Simple is better than complex -*-

Отредактировано terabayt (Апрель 12, 2015 15:01:12)

Офлайн

#5 Апрель 12, 2015 15:07:37

taxik
Зарегистрирован: 2015-04-12
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Протоколы итерации

terabayt
python 3
Согласен, но у вас С сразу поддерживает __next__(). А список или словарь нет.
Исходя из утверждения py.user.next, получается что при передаче в for если Python не находит у него __next__() то он вызывает к этому объекту iter()

Отредактировано taxik (Апрель 12, 2015 15:10:05)

Офлайн

#6 Апрель 12, 2015 15:09:54

terabayt
От: Киев
Зарегистрирован: 2011-11-26
Сообщения: 1099
Репутация: +  103  -
Профиль   Отправить e-mail  

Протоколы итерации

taxik
А список или словарь нет.

да ну
>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> dir(dict)
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']



————————————————
-*- Simple is better than complex -*-

Отредактировано terabayt (Апрель 12, 2015 15:10:32)

Офлайн

#7 Апрель 12, 2015 15:12:29

taxik
Зарегистрирован: 2015-04-12
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Протоколы итерации

terabayt
та ну
и где вы там __next__ нашли?.)

Офлайн

#8 Апрель 12, 2015 15:17:08

terabayt
От: Киев
Зарегистрирован: 2011-11-26
Сообщения: 1099
Репутация: +  103  -
Профиль   Отправить e-mail  

Протоколы итерации

taxik
и где вы там __next__ нашли?.)
ну если имеется __iter__, то соответственно
>>> dir([].__iter__())
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
>>> dir({}.__iter__())
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']



————————————————
-*- Simple is better than complex -*-

Офлайн

#9 Апрель 12, 2015 15:21:00

taxik
Зарегистрирован: 2015-04-12
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Протоколы итерации

terabayt
ну если имеется __iter__, то соответственно
Получается изначально он не содержит __next__, а полсе вызова __iter__ он добавляет ему метод __next__. Интересно что, если из вашего класса "C" удалить __next__ и вызвать к нему __iter__ он не добавит ему __next__, видимо это работает только для встроенных классов(или такой класс должен содержать доп. методы или атрибуты).

Отредактировано taxik (Апрель 12, 2015 15:24:47)

Офлайн

#10 Апрель 12, 2015 15:27:47

terabayt
От: Киев
Зарегистрирован: 2011-11-26
Сообщения: 1099
Репутация: +  103  -
Профиль   Отправить e-mail  

Протоколы итерации

taxik
Получается изначально он не содержит __next__, а полсе вызова __iter__ он добавляет ему метод __next__
не совсем
>>> a = [1,2]
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> a.__iter__()
<list_iterator object at 0x7fdcac999390>
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
__iter__ возвращает итератор, который имеет __next__
taxik
при передаче в for если Python не находит у него __next__() то он вызывает к этому объекту iter()
то будет ошибка
class C:
    def __init__(self, stop):
        self.current = 0
        self.stop = stop
    def __iter__(self):
        print('iter!!! ---')
        return self
for c in C(8):
    print(c)
iter!!! ---
Traceback (most recent call last):
  File "hello.py", line 10, in <module>
    for c in C(8):
TypeError: iter() returned non-iterator of type 'C'
и вот еще пример
class C:
    def __init__(self, stop):
        self.current = 0
        self.stop = stop
    def __iter__(self):
        print('iter!!! ---')
        return iter([1]*self.stop)
for c in C(8):
    print(c)



————————————————
-*- Simple is better than complex -*-

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version