How does iter() work, it's giving "TypeError: iter(v, w): v must be callable"
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Mysterious Puzzle
--
Chapters
00:00 How Does Iter() Work, It'S Giving &Quot;Typeerror: Iter(V, W): V Must Be Callable&Quot;
00:31 Answer 1 Score 3
01:05 Answer 2 Score 4
01:38 Accepted Answer Score 8
02:32 Answer 4 Score 5
03:21 Thank you
--
Full question
https://stackoverflow.com/questions/1985...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #python3x #iterator #typeerror
#avk47
ACCEPTED ANSWER
Score 8
From iter help:
iter(...)
iter(collection) -> iterator
iter(callable, sentinel) -> iteratorGet an iterator from an object. In the first form, the argument must supply its own iterator, or be a sequence. In the second form, the callable is called until it returns the sentinel.
You are mixing two variants of iter function. First one accepts collections, second accepts two arguments - function and sentinel value. You're trying to pass collection and sentinel value, which is wrong.
Short note: you can get a lot of interesting info from python's built-in help function. Simply type in python's console help(iter) and you'll get documentation on it.
Why does callabe(list) return true but callable(l) does not?
Because list is function which returns new list object. Function is callable (that's what function does - it gets called), while instance which this function returns - new list object - is not.
ANSWER 2
Score 5
When called with two arguments, iter takes a callable and a sentinel value. It's behavior is like it was implemented so:
def iter2args(f, sentinel):
    value = f()
    while value != sentinel:
        yield value
        value = f()
What gets passed in as f must be callable, which just means that you can call it like a function. The list builtin is a type object, which you use to create new list instances, by calling it like a function:
>>> list('abcde')
['a', 'b', 'c', 'd', 'e']
The list l you passed in is an existing list instance, which can't be used like a function:
>>> l = [1,2,3,4,5,6]
>>> l(3)
Traceback (most recent call last):
  File "<pyshell#20>", line 1, in <module>
    l(3)
TypeError: 'list' object is not callable
Thus, there is a large and important difference between the list type object and list instances, which shows up when using with iter. 
To iterate through a list until a sentinel is reached, you can use itertools.takewhile:
import itertools
for val in itertools.takewhile(l, lambda x: x!= 4):
    print(val) 
ANSWER 3
Score 4
It has to do with the second value being pass (a so called sentinel value), this ensures that the object being iterated over is a callable ie. a function.
So for every iteration that iter()does it calls __next__() on the object being passed.
iter() has two distinct behaviors,
- without a sentinel value
 - with a sentinel value
 
The example in the documentation is great for understanding it
with open("mydata.txt") as fp:
    for line in iter(fp.readline, "STOP"): #fp.readline is a function here.
        process_line(line)
ANSWER 4
Score 3
Have a look at docs: http://docs.python.org/2/library/functions.html#iter
When second argument in iter is present then first argument is treated very differently. It is supposed to be a function which is called in each step. If it returns sentinel (i.e. the second argument), then the iteration stops. For example:
l=[1,2,3,4,5,6]
index = -1
def fn():
    global index
    index += 1
    return l[index]
for val in iter(fn, 4):
    print (val)
EDIT: If you want to just loop over a list and stop when you see a sentinel, then I recommend doing simply this:
for val in l:
    # main body
    if val == 4:
        break