Skip to main content

How to Resolve Python "TypeError ... object is not iterable (in Python Functions/Methods)

Python TypeErrors like 'builtin_function_or_method' object is not iterable, 'method' object is not iterable, or 'function' object is not iterable (and their variations mentioning "argument of type...") are common mistakes, especially for beginners. These errors indicate that you are trying to use a function or method itself in a context that requires an iterable (like a for loop or the in operator), usually because you forgot to call the function or method using parentheses ().

This guide explains why functions/methods aren't directly iterable and provides the simple solution: ensure you call the function/method to get its (presumably iterable) return value.

Understanding the Error: Iterables vs. Callables (Functions/Methods)

  • Iterables: Objects that can be looped over, returning their items one by one (e.g., lists, tuples, strings, dictionaries, sets, file objects). They support operations like for item in iterable: and element in iterable.
  • Callables (Functions/Methods): Objects that can be called or invoked using parentheses (). They represent code to be executed. A function/method object itself is not a collection of items; it's a reference to the code block. Calling it (my_func()) executes the code and may return an iterable result.

This TypeError occurs because you provided the function/method object itself (the reference to the code) where Python expected an iterable sequence of items.

The Primary Cause: Missing Parentheses ()

The overwhelming reason for this error is simply forgetting to add the parentheses () after a function or method name when you intend to use the value it returns.

Forgetting to Call Built-in Methods (e.g., .keys(), .values(), .items(), .split())

my_dict = {'a': 1, 'b': 2}
my_string = "hello world"

try:
# ⛔️ TypeError: 'builtin_function_or_method' object is not iterable
# Trying to loop over the .keys method itself
for k in my_dict.keys: # Missing ()
print(k)
except TypeError as e:
print(f"Error looping over .keys: {e}")

try:
# ⛔️ TypeError: argument of type 'builtin_function_or_method' is not iterable
# Trying to check membership in the .split method itself
if "hello" in my_string.split: # Missing ()
print("Found")
except TypeError as e:
print(f"Error using 'in' with .split: {e}")

Forgetting to Call Custom Class Methods

class DataProvider:
def get_items(self):
return [10, 20, 30]

provider = DataProvider()

try:
# ⛔️ TypeError: 'method' object is not iterable
# Trying to loop over the get_items method itself
for item in provider.get_items: # Missing ()
print(item)
except TypeError as e:
print(f"Error looping over method: {e}")

Forgetting to Call Regular Functions

def generate_letters():
return ('x', 'y', 'z')

try:
# ⛔️ TypeError: 'function' object is not iterable
# Trying to loop over the generate_letters function itself
for letter in generate_letters: # Missing ()
print(letter)
except TypeError as e:
print(f"Error looping over function: {e}")

Contexts Where the Error Occurs

This error appears when you use the function/method reference where an iterable is expected:

In for Loops (...object is not iterable)

The for loop needs something it can request items from sequentially. A function/method object doesn't provide this capability directly.

With in Operator (argument of type... is not iterable)

The in operator checks for membership within a collection. It needs an iterable collection on the right-hand side to check against.

Solution: Add Parentheses () to Call the Function/Method

The fix is almost always to add the missing parentheses () after the function or method name. This invokes the callable, executes its code, and (presumably) returns the iterable object you intended to work with.

Fixing Built-in Method Calls:

my_dict = {'a': 1, 'b': 2}
my_string = "hello world"

# ✅ Call .keys()
print("Keys:")
for k in my_dict.keys():
print(k)

# ✅ Call .split()
print("Check in split result:")
if "hello" in my_string.split():
print("Found 'hello' in split parts")

Output:

Keys:
a
b
Check in split result:
Found 'hello' in split parts

Fixing Custom Method Call:

class DataProvider:
def get_items(self):
return [10, 20, 30]

provider = DataProvider() # Assuming DataProvider class from before
print("Items from custom method:")
# ✅ Call .get_items()
for item in provider.get_items():
print(item)

Output:

Items from custom method:
10
20
30

Fixing Regular Function Call

def generate_letters():
return ('x', 'y', 'z')

print("Letters from function:")
# ✅ Call generate_letters()
for letter in generate_letters():
print(letter)

Output:

Letters from function:
x
y
z

Secondary Cause: Name Shadowing (Conflicts)

Less commonly, the error might occur if you've accidentally defined a variable or function with the same name as a method, or vice-versa, causing Python to refer to the non-iterable callable when you intended to access an iterable attribute/variable.

# Example: Function name conflicts with list variable
get_data = [100, 200] # This variable holds a list

def get_data(): # This function has the SAME NAME
return [1, 2, 3]

try:
# ⛔️ TypeError: 'function' object is not iterable
# Because the function definition shadowed the list variable,
# 'get_data' now refers to the function, not the list.
for item in get_data:
print(item)
except TypeError as e:
print(f"Name conflict error: {e}")

Solution: Rename Conflicting Variables/Functions/Methods

If name shadowing is the issue, rename either the variable or the function/method so they have unique names within their scope.

data_list = [100, 200] # Renamed variable

def get_data():
return [1, 2, 3]

# ✅ Now iterates over the list correctly
print("Iterating over data_list:")
for item in data_list:
print(item) # Output: 100, 200

# ✅ And the function can still be called separately
print("Calling get_data():")
result_from_func = get_data()
print(result_from_func) # Output: [1, 2, 3]

Output:

Iterating over data_list:
100
200
Calling get_data():
[1, 2, 3]

Debugging the Error

  1. Check for Parentheses: Look closely at the line indicated in the TypeError traceback. Is there a function or method name immediately followed by the for ... in or the in operator without parentheses ()? Add them.
  2. Check type(): If adding parentheses doesn't work or seems wrong, print the type of the object you're trying to iterate over right before the loop/in check:
    print(f"DEBUG: Type is {type(object_before_iteration)}")
    If it outputs <class 'function'>, <class 'method'>, or <class 'builtin_function_or_method'>, you definitely forgot to call it.
  3. Check for Name Conflicts: If the type seems correct (e.g., <class 'list'>) but you still get the error referring to a function/method, check if you've accidentally redefined a name (shadowing).

Checking if an Object is Iterable (Optional)

You can programmatically check if an object is iterable using try...except with iter(), although this isn't usually necessary for fixing this specific error (where the fix is almost always adding ()).

from collections.abc import Iterable

def my_func(): return [1]
my_list = [1]

def check_iter(obj_name_str, obj):
print(f"Checking '{obj_name_str}' ({type(obj)}):")
try:
iter(obj)
print(" --> Iterable (via iter())")
except TypeError:
print(" --> NOT Iterable (via iter())")
# Python 3.3+ alternative:
# print(f" --> Iterable (via isinstance)? {isinstance(obj, Iterable)}")

check_iter("my_func", my_func) # Not Iterable
check_iter("my_func()", my_func()) # Iterable
check_iter("my_list", my_list) # Iterable
check_iter("my_dict.keys", {}.keys) # Not Iterable
check_iter("my_dict.keys()", {}.keys()) # Iterable

Output:

Checking 'my_func' (<class 'function'>):
--> NOT Iterable (via iter())
Checking 'my_func()' (<class 'list'>):
--> Iterable (via iter())
Checking 'my_list' (<class 'list'>):
--> Iterable (via iter())
Checking 'my_dict.keys' (<class 'builtin_function_or_method'>):
--> NOT Iterable (via iter())
Checking 'my_dict.keys()' (<class 'dict_keys'>):
--> Iterable (via iter())

Conclusion

The family of errors TypeError: '...' object is not iterable involving function, method, or builtin_function_or_method almost always means you forgot the parentheses () needed to call the function or method. Instead of iterating over the result returned by the callable, your code is attempting (and failing) to iterate over the callable object itself.

The fix is simple: Add the parentheses () to invoke the function/method (e.g., change my_dict.keys to my_dict.keys(), my_func to my_func()). Also, be mindful of potential name shadowing issues where variables and functions/methods might share names.