Understanding input in iter
Question:
I was looking for solutions to take multiline input in python. I found this answer which uses the following code.
sentinel = '' # ends when this string is seen
for line in iter(input, sentinel):
pass # do things here
I read from the python docs that if iter
recieves the second argument then it will call the __next__()
of the first argument. But I don’t think input
has the __next__()
implemented (I am not able to verify this either through the docs or surfing through the source code). Can someone explain how it’s working?
Also, I observed this weird behaviour with the following code.
sentinel = ''
itr = iter(input, sentinel)
print("Hello")
print(set(itr))
Here is the output
[dvsingla Documents]$ python3 temp.py
Hello
lksfjal
falkja
aldfj
{' aldfj', 'falkja', 'lksfjal'}
[dvsingla Documents]$
The prompt starts taking input after printing Hello which is not following line by line interpretation.
Thanks for any help
Answers:
iter
has three forms: two one-arg and a two-arg version. The first one-arg version is the one that you are likely more familiar with.
-
If object
supports __iter__
, iter
will call that and return the result.
-
If not, iter
will look for __getitem__
(which is assumed to accept integers at that point) and __len__
. If both are found in object
, iter
will instantiate its own internal iterator type that has a __next__
method which increments the index to object.__getitem__
calls until it reaches __len__
.
-
The two-arg form is much less used (and probably less known). It takes two arguments: object
is a no-arg callable, and sentinel
is a value that will be compared to what object
returns to determine the end of iteration. In this case iter
returns an instance of an internal class which supports __next__
, just like for #2. Each call to __next__
will delegate to object
until it returns sentinel
. That’s the version that you see being used here.
In all three cases, object
itself does not need to implement __next__
directly. The iterator returned by iter
does. For case #1, that’s something object
produces. For cases #2 and #3, is a wrapper made by iter
.
The reason that the printouts happen as they do is that all forms of iter
return a lazy iterator, not just the first form. itr
will not execute anything until the call to set
, which will repeatedly call input
through itr.__next__()
. This will continue until the user enters an empty line, which will be equal to the chosen sentinel
.
I was looking for solutions to take multiline input in python. I found this answer which uses the following code.
sentinel = '' # ends when this string is seen
for line in iter(input, sentinel):
pass # do things here
I read from the python docs that if iter
recieves the second argument then it will call the __next__()
of the first argument. But I don’t think input
has the __next__()
implemented (I am not able to verify this either through the docs or surfing through the source code). Can someone explain how it’s working?
Also, I observed this weird behaviour with the following code.
sentinel = ''
itr = iter(input, sentinel)
print("Hello")
print(set(itr))
Here is the output
[dvsingla Documents]$ python3 temp.py
Hello
lksfjal
falkja
aldfj
{' aldfj', 'falkja', 'lksfjal'}
[dvsingla Documents]$
The prompt starts taking input after printing Hello which is not following line by line interpretation.
Thanks for any help
iter
has three forms: two one-arg and a two-arg version. The first one-arg version is the one that you are likely more familiar with.
-
If
object
supports__iter__
,iter
will call that and return the result. -
If not,
iter
will look for__getitem__
(which is assumed to accept integers at that point) and__len__
. If both are found inobject
,iter
will instantiate its own internal iterator type that has a__next__
method which increments the index toobject.__getitem__
calls until it reaches__len__
. -
The two-arg form is much less used (and probably less known). It takes two arguments:
object
is a no-arg callable, andsentinel
is a value that will be compared to whatobject
returns to determine the end of iteration. In this caseiter
returns an instance of an internal class which supports__next__
, just like for #2. Each call to__next__
will delegate toobject
until it returnssentinel
. That’s the version that you see being used here.
In all three cases, object
itself does not need to implement __next__
directly. The iterator returned by iter
does. For case #1, that’s something object
produces. For cases #2 and #3, is a wrapper made by iter
.
The reason that the printouts happen as they do is that all forms of iter
return a lazy iterator, not just the first form. itr
will not execute anything until the call to set
, which will repeatedly call input
through itr.__next__()
. This will continue until the user enters an empty line, which will be equal to the chosen sentinel
.