Почему перечислите, почтовый индекс, типы диапазона не принадлежат типам. GeneratorType? - PullRequest
0 голосов
/ 24 октября 2018

В Python 3 введены объекты типа генератора, которые возвращаются при вызове range() и zip().Возвращаемый объект действует как генератор, и его можно итерировать один раз, но он плохо «печатается», очень похоже на аргумент enumerate() return.

Я был озадачен, увидев, однако, что они являются различными типами объектов и не относятся к types.GeneratorType, или, по крайней мере, это то, что показывает модуль types.Функция, которая будет работать, например, ожидает, что генератор не обнаружит их.Каково их наследство?Принадлежат ли они к основной структуре «генератора», чтобы, например, их можно было идентифицировать вместе с другими генераторами?

import types

a = [1,2,3]
b = [4,5,6]

# create some generator-type objects
obj_zip = zip(a,b)
obj_enu = enumerate(a)
obj_r = range(10)

print(type(obj_zip))
print(type(obj_enu))
print(type(obj_r))

# checking against types.GeneratorType returns False
print(isinstance(obj_zip,types.GeneratorType))
print(isinstance(obj_enu,types.GeneratorType))
print(isinstance(obj_r,types.GeneratorType))

# checking against their own distinct object types returns True
print(isinstance(obj_zip,zip))

Ответы [ 3 ]

0 голосов
/ 24 октября 2018

Per GeneratorType документы :

types.GeneratorType

Тип объектов генератора-итератора, созданных функциями генератора.

Функции генератора - это специфическая вещь в языке;это означает функции, которые используют yield или yield from (или выражения генератора, которые являются просто сокращением для встроенных функций генератора).Это подмножество набора итераторов (все, что вы можете вызвать next() для получения нового значения), которое, в свою очередь, является подмножеством итераций (все, что вы можете вызвать iter() для получения итератора;сами итераторы являются итераторами, где iter(iterator) ведет себя как единичная функция).

По сути, если вы проверяете «могу ли я зацикливаться на этом?», тестируйте isinstance(obj, collections.abc.Iterable).Если вы проверяете "это исчерпывающий итератор?"(то есть, я исчерпал его, зацикливаясь на нем?), протестируйте либо isinstance(obj, collections.abc.Iterator), либо для подхода, основанного на типизировании утки, протестируйте iter(obj) is obj (инварианты итераторов требуют , что iter(iterator) даетисходный объект итератора не изменился).

Обратите внимание, что range является , а не генератором или итератором.По документам :

Вместо того, чтобы быть функцией, диапазон на самом деле является типом неизменяемой последовательности, как описано в Диапазоны и Типы последовательностей -list, tuple, range .

Быть неизменным типом последовательности означает, что является итеративным, но это так.Тот факт, что он обычно используется как итератор, не имеет значения;если бы это был итератор, второй цикл здесь никогда бы не выполнялся:

r = range(3)
for i in r:
    print("First", i)
for i in r:
    print("Second", i)

, но он работает просто отлично, потому что каждый (неявный) вызов iter(r) возвращает new itera tor на основе той же базовой итеры ble .

0 голосов
/ 24 октября 2018

не предназначен для полного ответа ( ответ ShadowRanger уже все объясняет), но просто для того, чтобы указать, что types.GeneratorType действительно очень ограниченный тип, как показано в types.py source:

def _g():
    yield 1
GeneratorType = type(_g())

это только область действия функций генератора.Другие «похожие на генератор» объекты не используют yield, поэтому они не совпадают.

0 голосов
/ 24 октября 2018

В документации сказано, что перечисление функционально эквивалентно генератору.На самом деле он реализован на C и возвращает итератор, а не генератор, как описано в . Enumerate () создает объект генератора .Генераторы и итерации практически одинаковы.Это подробно объясняется в Разница между генераторами и итераторами Python .

Я предполагаю, что вы пытаетесь решить реальную проблему, например, выяснить, можете ли вы что-то перебрать.Чтобы решить это, вы можете проверить, является ли что-то экземпляром collections.Iterable.

a = enumerate([1,2,3])
isinstance(a, collections.Iterable)
>>> True
...