Back to Blog
Python

Python hasattr: Checking Object Attributes

Learn how Python's hasattr() checks object attributes, handles exceptions, and when to prefer getattr() or try/except.

hasattrPython builtinsattribute checkingduck typinggetattr
Illustration of Python hasattr checking whether an object contains an attribute, shown as a magnifying glass over a Python object diagram.

What hasattr() Does and Its Syntax

hasattr() is a built-in Python function that reports whether an object has a given attribute. It accepts two arguments: the object to inspect and the attribute name as a string. The return value is a boolean: True when the attribute exists, False when it does not.

class Config: timeout = 30 config = Config() print(hasattr(config, "timeout")) # True print(hasattr(config, "retries")) # False

The attribute name is passed as a string, so you can check for attributes whose names are determined at runtime. This is useful when working with dynamic data, such as configuration keys or serialized object fields.

How hasattr() Works Internally

Understanding the implementation explains most of the function's behavior. hasattr() calls getattr(obj, name) and catches AttributeError. If getattr() raises AttributeError, hasattr() returns False; otherwise it returns True.

This has a subtle consequence: hasattr() returns False not only when an attribute is genuinely missing, but also when accessing the attribute raises AttributeError for any other reason. A property getter that raises AttributeError internally will make hasattr() report False, even though the attribute is defined on the class.

The Property Getter Edge Case

Consider a class where a property getter raises AttributeError because some underlying state is missing:

class User: def __init__(self, name=None): self._name = name @property def name(self): if self._name is None: raise AttributeError("name is not set") return self._name user = User() print(hasattr(user, "name")) # False

The attribute name is defined on the class, but hasattr() returns False because the getter raises AttributeError. If you use hasattr() to decide whether to access user.name, you will skip it even though the attribute exists. This can hide the real problem: the name was never set.

A more robust pattern is to check the underlying state directly, or to use getattr() with a default and handle the missing case explicitly:

name = getattr(user, "_name", None) if name is None: name = "anonymous"

hasattr() vs getattr() with a Default

getattr(obj, "attr", default) returns the attribute value if it exists, or the default value otherwise. This is often more useful than hasattr() because it gives you the value in one step.

timeout = getattr(config, "timeout", 30)

If you use hasattr() and then getattr() separately, you perform the attribute lookup twice. Between those calls, the object may change, so the attribute you checked for may not be the one you retrieve. Using getattr() with a default avoids both problems.

hasattr() vs try/except

When you need both the existence check and the value, a try/except block is the most explicit approach:

try: value = obj.attribute except AttributeError: value = fallback

This performs a single lookup. It also lets you choose which exceptions to treat as fallback cases: either only AttributeError, or a broader set raised by a property getter. hasattr(), by contrast, always catches AttributeError, so it cannot distinguish a genuinely missing attribute from a property getter that raises AttributeError internally.

Performance Considerations

hasattr() performs a full attribute lookup, which for class attributes involves traversing the object's __dict__ and its class's MRO. When the attribute is a property, the getter runs as well. The exception handling inside hasattr() also has a cost when the attribute is missing, because raising and catching an exception is slower than a simple lookup.

For code that checks the same attribute repeatedly, such as inside a loop, the cost adds up. If you only need the value, getattr() with a default is faster and clearer. If you need to distinguish between "attribute missing" and "attribute present but invalid," hasattr() is the wrong tool because it cannot make that distinction.

When hasattr() Is the Right Choice

hasattr() fits best when you need a quick boolean check and do not need the value. Typical cases include duck typing checks, where you verify that an object supports a method or attribute before calling it:

if hasattr(obj, "save"): obj.save()

It is also useful for optional attributes on objects from external libraries where you cannot modify the class. In those situations, hasattr() keeps the code short and readable, as long as you are aware that property getters raising AttributeError will produce a False result.

Python hasattr() Explained: Syntax, Edge Cases, and Alternatives | RYUSLOG DEV