How does iter() work, it's giving "TypeError: iter(v, w): v must be callable"

From iter help:

iter(...)
iter(collection) -> iterator
iter(callable, sentinel) -> iterator

Get 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.


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) 

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)