2016-06-13 5 views
0

Я прочитал несколько сообщений о stackoverflow о том, как проверить объект, является итератором в Python, но кажется, что они не решили мой вопрос. У меня есть этот пример из книги Эффективного PythonПутаница о одном примере, чтобы проверить, является ли объект итератором в Python

def normalize_defensive(numbers): 
    if iter(numbers) is iter(numbers): # An iterator — bad! 
     raise TypeError(‘Must supply a container’) 
    total = sum(numbers) 
    result = [] 
    for value in numbers: 
     percent = 100 * value/total 
     result.append(percent) 
    return result 

Применение:

visits = [15, 35, 80] 
normalize_defensive(visits) # No error 
visits = ReadVisits(path) # ReadVisits is a class with an __iter__ method. 
normalize_defensive(visits) # No error 
it = iter(visits) 
normalize_defensive(it) 
>>> 
TypeError: Must supply a container 

Так что мой вопрос в этой строке:

if iter(numbers) is iter(numbers): # An iterator — bad! 

Почему эта проверка строки, если переменный числа - это итератор? Когда посещения = [15, 35, 80], должно ли быть верно, что iter(numbers) is iter(numbers)?

ответ

2

Когда вы называете итерацию, вызывая iter() на такой объект всегда будет производить новый объект итератора. Но при вызове iter() на итератор всегда будет возвращать тот же объект; это требование iterator protocol, что они делают.

От iterator.__iter__() documentation:

Возвращение сам итератор объекта. Это необходимо для использования как контейнеров, так и итераторов с операторами for и in.

Поскольку iter(iterable) всегда возвращает сам, тест iter(obj) is iter(obj) будет верно; тот же объект возвращается в обоих случаях.

+1

Будет ли 'iter (obj) работать obj'? –

+1

@StefanPochmann: это было бы. –

0

Чтобы помочь вам понять объяснение Мартейн, взять взглянуть на следующее:

>>> numbers = [15, 35, 80] 
>>> it = iter(numbers) 
>>> it2 = iter(numbers) 
>>> it3 = iter(it) 
>>> id(it1) 
51123792 
>>> id(it2) 
51056464 # id of it2 is different from it1 
>>> id(it3) 
51123792 # iterator of iterator it3 has the same id as iterator it1 

Так что, если numbers был iterator, называя iter на numbers всегда будет возвращать объекты, которые внутренне идентичны: iter(numbers) is iter(numbers) будет True.