AttributeError
AttributeError
is a built-in exception that occurs when you attempt to access a method or attribute that isn’t defined for the object in question.
You should handle this exception to ensure your code doesn’t crash. Catching an AttributeError
allows you to provide a graceful degradation or alternative solution when users try to access an attribute that’s missing.
AttributeError
Practical Use Cases
- Accessing a method or attribute that doesn’t exist in a class or module
- Using the wrong attribute name due to a typo
- Accessing an attribute that was supposed to be dynamically added but hasn’t been initialized yet
- Attempting to access attributes on a
NoneType
object due to uninitialized or improperly assigned variables
AttributeError
Examples
An example of when the exception appears:
>>> class Dog:
... def bark(self):
... print("Woof!")
...
>>> dog = Dog()
>>> dog.meow()
Traceback (most recent call last):
...
AttributeError: 'Dog' object has no attribute 'meow'
An example of how to handle the exception:
>>> class Dog:
... def bark(self):
... print("Woof!")
...
>>> dog = Dog()
>>> try:
... dog.meow()
... except AttributeError:
... print("The Dog class doesn't have a 'meow' method.")
...
The Dog class doesn't have a 'meow' method.
Every Python object will raise an AttributeError
when you attempt to access a non-existent attribute on it. When you need to implement custom logic, then you can edit .__getattr__()
accordingly before raising the error manually:
>>> class CustomObject:
... def __getattr__(self, name):
... # Write to logs
... raise AttributeError(f"No '{name}' here.")
...
>>> obj = CustomObject()
>>> obj.missing_attribute
Traceback (most recent call last):
...
AttributeError: No 'missing_attribute' here.
You could also provide fallback mechanisms for the lookup before raising the AttributeError
. Raising it manually also allows you to customize the error message.
AttributeError
How to Fix It
For example, say that you have a Pen
class with a .color
attribute:
>>> class Pen:
... def __init__(self, color):
... self.color = color
...
>>> pen = Pen("black")
>>> pen.color
'black'
>>> pen.colour
Traceback (most recent call last):
...
AttributeError: 'Pen' object has no attribute 'colour'.
⮑ Did you mean: 'color'?
The class works correctly with .color
but fails with .colour
. To fix the above code, you could customize the attribute lookup in .__getattr__()
before raising AttributeError
manually:
class Pen:
def __init__(self, color):
self._color = color
def __getattr__(self, name):
if name in ["color", "colour"]:
return self._color
else:
raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
def __setattr__(self, name, value):
if name in ["color", "colour"]:
super().__setattr__("_color", value)
else:
super().__setattr__(name, value)
With these edits to Pen
, you users can now access the ._color
attribute with both .color
and .colour
:
>>> pen = Pen("black")
>>> pen.color
'black'
>>> pen.colour
'black'
>>> pen.stroke
Traceback (most recent call last):
...
AttributeError: 'Pen' object has no attribute 'stroke'
At the same time, the class still raises an AttributeError
when you try to access a non-existent attribute.
Note that you need to manually raise AttributeError
in .__getattr__()
if you overwrite the default implementation with your custom logic. Otherwise, you break the default behavior of raising an AttributeError
when looking up a non-existent attribute.
Related Resources
Tutorial
Python's Built-in Exceptions: A Walkthrough With Examples
In this tutorial, you'll get to know some of the most commonly used built-in exceptions in Python. You'll learn when these exceptions can appear in your code and how to handle them. Finally, you'll learn how to raise some of these exceptions in your code.
For additional information on related topics, take a look at the following resources: