How to fix "‘bool’ object is not callable" in Python
Tags: python, programming
Published: 2023-02-02 21:01:20

> ✋ **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-bool-object-is-not-callable-fix) for a 💯 user experience. _~reza_

The “TypeError: ‘bool’ object is not callable” error occurs when you try to call a boolean value (`bool` object) as if it was a function!

Here’s what the error looks like:

```
Traceback (most recent call last):
  File /dwd/sandbox/test.py, line 3, in <module>
    if is_active() == true:
       ^^^^^^^^^^^
TypeError: 'bool' object is not callable
```

In the simplest terms, this is what happens:

```python
is_active = True

# ⚠️ is_active is a boolean value not a callable
if is_active() == True:
    print('User is active.')
```

Calling a boolean value like a callable isn't what you'd do on purpose, though. It usually happens due to unwanted value assignments. Or accidentally overriding a function's global name with `True` or `False`!

To fix the issue, trace the error back up to the statement that changed your function to a boolean value.

Additionally, if you accidentally put an extra parenthesis after a built-in or user-defined function that returns a boolean value, you'll get the error:

```python
# 🚫 Raises TypeError: 'bool' object is not callable
bool()()
```

In the above example, `bool()` returns `False`, and having an extra pair of parenthesis is like `False()`.

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

First, inspect the respective function's value, and figure out how it ended up being a boolean object in the first place.

Sometimes figuring this out might be tricky. Below are three scenarios that lead to the "TypeError: 'bool' object is not callable" error:

1. <u>Declaring variable with a name that's also the name of a function</u>
2. <u>Calling a method that's also the name of a property</u>
3. <u>Calling a method decorated with `@property`</u>

Let's explore each scenario with some examples.

**Declaring a variable 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 `int`, `float`, `dict`, `list`, etc. 

All built-in functions are defined in the `builtins` module and assigned a global name for easier access. For instance, `str()` is `__builtins__.str()`.

That said, overriding a function (accidentally or on purpose) with another value is technically possible. 

For instance, if you define a variable named `str` and initialize it with a boolean value, it'll no longer point to the `str` class.

```python
# ⚠️ the value of the built-in function str() is changed to True
str = True
score = 15

# 🚫 Raises TypeError
print ('The score is: ' + str(score))
```
If you run the above code, Python will complain with a "TypeError: 'bool' object is not callable" error because `True` (the new value of `str`) isn't callable.

You have two ways to fix the issue:

- Rename the variable `str`
- Explicitly access the str function from the builtins module (`__bultins__.str`)

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:

```python
status = True
score = 15

print ('The score is: ' + str(score))
# Output: The score is: 15
```

> ⚠️ 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: 'bool' 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, published):
        self.title = title
        self.published = published

    def published(self):
        return self.published


book = Book('Learning Python', True)

# 🚫 Raises TypeError: 'bool' object is not callable
if book.published():
    print('The book is published.')
```

In the above code, class Book contains a property named `published` that defines whether the books is published or not. Further down, we defined a method, also named `published`.

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

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

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

    def is_published(self):
        return self.published


book = Book('Learning Python', True)

if book.is_published():
    print('The book is published.')
# Output: The book is published.
```

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

```python
class User:
    def __init__(self, user_id, active):
        self._user_id = user_id
        self._active = active

    @property
    def active(self):
        return self._active


user = User(1, True)

# 🚫 Raises TypeError: 'bool' object is not callable
if user.active():
    print('User is active!')
```

You need to access the getter method without the parentheses:

```python
class User:
    def __init__(self, user_id, active):
        self._user_id = user_id
        self._active = active

    @property
    def active(self):
        return self._active


user = User(1, True)

if user.active:
    print('User is active!')

# Output: User is active!
```

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: ‘tuple’ object is not callable in Python](https://www.decodingweb.dev/python-typeerror-tuple-object-is-not-callable-fix)
- [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)