jukhamil
jukhamil

Reputation: 819

Why is the dict.keys not iterable?

node_name is a string. Shouldn't this return a list of keys in the node_list dictionary, which can be iterated over? Why does the error say it is not iterable?

class Graph:

def __init__(self):
    self.node_list = {}
    self.number = 0

def node(self, node_name):
    if node_name in self.node_list.keys: 
    ...

File "PythonProject2.3.py", line 10, in node
    if node_name in self.node_list.keys: #returns list of keys
TypeError: argument of type 'builtin_function_or_method' is not iterable

Upvotes: 4

Views: 9620

Answers (3)

Steve Jessop
Steve Jessop

Reputation: 279315

Python sees node_name in self.node_list.keys, so it evaluates self.node_list.keys and then tries to work out whether or not node_name is in the result of that.

self.node_list.keys is a function (you should have written keys()), but all that's really relevant here is that it doesn't support the Python in operator. That is to say, you can't test whether or not something is in self.node_list.keys.

The reason you specifically get an error about iteration, is that Python first checks for the __contains__ function and, if not present, tries to iterate over the right-hand operand of in comparing each value against the left-operand using ==. This fails, hence the exception you saw. The reason Python does that is just so that anything which supports iteration also supports in automatically. Albeit perhaps not very efficiently.

Upvotes: 0

张文辉
张文辉

Reputation: 1

Please change

if node_name in self.node_list.keys(): 

to

if self.node_list.has_key(node_name):

Upvotes: 0

mipadi
mipadi

Reputation: 410922

.keys is a function, not a property. Try this instead:

if node_name in self.node_list.keys():

A dictionary iterates over its keys by default, though, so this will work, too:

if node_name in self.node_list:

Upvotes: 12

Related Questions