How to fix "‘tuple’ object is not callable" in Python
Tags: python, programming
Published: 2023-02-03 11:50:45

> ✋ **Update:** This post was originally published on my blog [decodingweb.dev](https://www.decodingweb.dev), where you can read the [latest version](https://www.decodingweb.dev/python-typeerror-tuple-object-is-not-callable-fix) for a 💯 user experience. _~reza_

The “TypeError: ‘tuple’ object is not callable” error occurs when you try to call a tuple as if it was a function!

Here’s what the error looks like:

```
Traceback (most recent call last):
  File "/dwd/sandbox/test.py", line 4, in 
    print(range_config('title'))
          ^^^^^^^^^^^^^^^^^^^^^
TypeError: 'tuple' object is not callable
```

Calling a tuple object as if it's a callable isn't what you'd do on purpose, though. It usually happens due to a wrong syntax or accidentally overriding a function's global name with a tuple object!

Let's explore the common causes and their solutions.

## How to fix TypeError: 'tuple' object is not callable?

This TypeError happens under various scenarios:

1. <u>Accessing a tuple item by `()` rather than `[]`</u>
2. <u>A missing comma before a nested tuple</u>
3. <u>Defining a tuple with a global name that's also the name of a function</u>
4. <u>Calling a method that's also the name of a property</u>
5. <u>Calling a method decorated with `@property`</u>

**Accessing a tuple item by parenthesis rather than square brackets:** The most common cause of this TypeError is accessing a tuple item by `()` instead of `[]`.

Based on Python semantics, any identifier followed by a `()` is a function call. In this case, since `()` follows a tuple, it's like you're trying to call the tuple like it's callable.

As a result, you'll get the "TypeError: ‘tuple’ object is not callable" error.

```python
range_config = (1, 10)

 # ⛔ Raises: TypeError: ‘tuple’ object is not callable
print(range_config(0))
```

This is how you're supposed to access a tuple value:

```python
range_config = (1, 10)

# You should access a value in a tuple by []
print(range_config[0])
```

**A missing comma before a nested tuple:** Unlike other sequence data types, you can create tuples in a variety of ways. Understanding tuple syntax helps you avoid confusion while debugging this issue.

As you already know, a tuple consists of several values separated by commas (with or without surrounding parentheses).

When creating tuples, remember:

1. You can create tuples without parenthesis
2. `()` creates an empty tuple
3. Tuples with one item need a comma at the end: `(12,)`

Here are some examples in a Python Shell:

```python
>>> 3984, 'someValue', True
(3984, 'someValue', True)
>>>
>>> ()
()
>>>
>>> ((),)
((),)
>>>
>>> (3984,)
(3984,)
>>>
>>> tuple([1, 2, 3])
(1, 2, 3)
>>>
>>> 3984, 'someValue', ('nestTupleValue',), ('nestedTupleValue', 2345)
(3984, 'someValue', ('nestTupleValue',), ('nestedTupleValue', 2345))
```

But how a missing comma can lead to this TypeError? You may ask.

Let's see an example:

```python
>>> 3984, 'someValue', ('nestTupleValue',) ('nestedTupleValue', 2345)

<stdin>:1: SyntaxWarning: 'tuple' object is not callable; perhaps you missed a comma?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object is not callable
```

In the above example, the last two items in our tuple are also tuples (nested tuple). However, a comma is missing between them. As a result, Python's interpreter doesn't include the last item in the tuple. Consequently, it thinks we're trying to call our tuple with two arguments, meaning `'nestedTupleValue'` and `2345`.

Since a tuple isn't a callable, you get the TypeError. 

That said, whenever you get this error at a specific line, check if you've missed a comma before a nested tuple.

**Defining a tuple with a name that's also the name of a function:** A Python function is an object like any other built-in object, such as `str`, `int`, `float`, `dict`, `tuple`, `list`, etc.

All built-in functions are defined in the `builtins` module and assigned a global name for easier access. For instance, the global name tuple refers to the tuple class.

That said, overriding a function's global name (accidentally or on purpose) with any value (e.g., a tuple) is technically possible. 

In the following example, we've declared a variable named `range` containing some config data in a tuple. In its following line, we use the `range()` function in a for loop:

```python
# Creating tuple named range
range = (1, 10)
# ⚠️ The above line overrides the original value of range (the 'range' class)

for i in range(5, 15, 2):
    print(i)
```

If you run the above code, Python will complain with a "TypeError: 'tuple' object is not callable" error because we've already assigned the `range` global variable to our tuple.

We have two ways to fix the issue:

1. Rename the variable `range`
2. Explicitly access the `range()` function from the builtins module (`__bultins__.range`)

The second approach isn't recommended unless you're developing a module. For instance, if you want to implement an `open()` function that wraps the built-in `open()`:

```python
# Custom open() function using the built-in open() internally
def open(filename):
     # ...
     __builtins__.open(filename, 'w', opener=opener)
     # ...
```

In almost every other case, you should always avoid naming your variables as existing functions and methods. But if you've done so, renaming the variable would solve the issue.

So the above example could be fixed like this:

This issue is common with function names you're more likely to use as variable names. Functions such as vars, locals, list, tuple, all, or even user-defined functions.

⚠️ Long story short, you should never use a function name (built-in or user-defined) for your variables!

Overriding functions (and calling them later on) is one of the most common causes of the "TypeError: 'tuple' object is not callable" error. It's similar to calling integer numbers.

Now, let's get to the less common mistakes that lead to this error.

**Calling a method that's also the name of a property:** When you define a property in a class constructor, it'll shadow any other attribute of the same name.

```python
class Book:
    def __init__(self, title, authors):
        self.title = title
        self.authors = authors

    def authors(self):
        return self.authors

authors = ('Andy Hunt', 'Dave Thomas')
book = Book('Head First Python', authors)

print(book.authors())
# 👆 ⛔ Raises TypeError: 'dict' object is not callable
```

In the above example, we have a property named `authors` - a tuple to keep the authors' names. Further down, we defined a method, also named `authors`.

However the property authors shadows the method. As a result, any reference to `authors` returns the property - a tuple object - not the method. And if you try to call this tuple object, you should expect the "TypeError: ‘tuple’ object is not callable" error.

The name `get_authors` sounds like a safer and more readable alternative:

```python
class Book:
    def __init__(self, title, authors):
        self.title = title
        self.authors = authors

    def get_authors(self):
        return self.authors

authors = ('Andy Hunt', 'Dave Thomas')
book = Book('Head First Python', authors)

print(book.get_authors())
# Output: ('Andy Hunt', 'Dave Thomas')
```

**Calling a method decorated with `@property` decorator:** The `@property` decorator turns a method into a “getter” for a read-only attribute of the same name. You need to access a getter method without parenthesis, otherwise you'll get a TypeError.

```python
class Book:
    def __init__(self, title, authors):
        self._title = title
        self._authors = authors

    @property
    def authors(self):
        return self._authors

authors = ('Andy Hunt', 'Dave Thomas')
book = Book('Head First Python', authors)

print(book.authors())
# 👆 ⛔ Raises TypeError: 'tuple' object is not callable
```

To fix it, you need to access the getter method without the parentheses:

```python
class Book:
    def __init__(self, title, authors):
        self._title = title
        self._authors = authors

    @property
    def authors(self):
        return self._authors

authors = ('Andy Hunt', 'Dave Thomas')
book = Book('Head First Python', authors)

print(book.authors)
# Output: ('Andy Hunt', 'Dave Thomas')
```

Problem solved!

Alright, I think it does it! I hope this quick guide helped you fix your problem.

Thanks for reading.

**❤️ You might like:**

- [TypeError: ‘dict’ object is not callable in Python](https://www.decodingweb.dev/python-typeerror-dict-object-is-not-callable-fix)
- [TypeError: ‘list’ object is not callable in Python](https://www.decodingweb.dev/python-typeerror-list-object-is-not-callable-fix)
- [TypeError: ‘str’ object is not callable in Python](https://www.decodingweb.dev/python-typeerror-str-object-is-not-callable-fix)
- [TypeError: ‘float’ object is not callable" in Python](https://www.decodingweb.dev/python-typeerror-float-object-is-not-callable-fix)
- [TypeError: 'int' object is not callable in Python](https://www.decodingweb.dev/python-typeerror-int-object-is-not-callable-fix)