ZetCode

Python hasattr Function

Last modified April 11, 2025

This comprehensive guide explores Python's hasattr function, which checks for attribute existence in objects. We'll cover basic usage, class inheritance, dynamic attributes, and practical examples of introspection.

Basic Definitions

The hasattr function checks if an object has a given attribute. It returns True if the attribute exists, False otherwise. This is safer than direct attribute access with try/except.

Key characteristics: takes an object and attribute name string as arguments. Works with all Python objects including classes, instances, modules, and built-in types. Part of Python's introspection capabilities.

Basic Attribute Checking

Here's simple usage showing how hasattr checks for attributes in different types of objects including classes and instances.

basic_hasattr.py
class Person:
    def __init__(self, name):
        self.name = name

p = Person("Alice")

# Check instance attributes
print(hasattr(p, 'name'))    # True
print(hasattr(p, 'age'))     # False

# Check class attributes
print(hasattr(Person, '__init__'))  # True
print(hasattr(Person, 'species'))   # False

This example shows hasattr checking both instance and class attributes. It safely checks for existence without raising AttributeError.

The function works with any attribute name including methods (like __init__) and regular data attributes (like name).

Inheritance and hasattr

hasattr works with inheritance hierarchies, checking both the instance and its class hierarchy for attributes. This example demonstrates.

inheritance.py
class Animal:
    def __init__(self):
        self.kingdom = "Animalia"

class Dog(Animal):
    def __init__(self, name):
        super().__init__()
        self.name = name
    
    def bark(self):
        return "Woof!"

buddy = Dog("Buddy")

# Check inherited attributes
print(hasattr(buddy, 'name'))      # True (instance)
print(hasattr(buddy, 'kingdom'))   # True (parent class)
print(hasattr(buddy, 'bark'))      # True (class method)
print(hasattr(buddy, 'species'))   # False (nonexistent)

hasattr correctly identifies attributes from the instance, its class, and parent classes. This makes it useful for checking API compliance.

The function follows Python's attribute lookup rules, checking the full method resolution order (MRO) for classes.

Dynamic Attributes

hasattr can check for dynamically added attributes, including those created with setattr or through property decorators.

dynamic.py
class DynamicAttributes:
    def __init__(self):
        self.initial = "value"
    
    @property
    def computed(self):
        return 42

obj = DynamicAttributes()
setattr(obj, 'dynamic', 'new value')

print(hasattr(obj, 'initial'))    # True (regular)
print(hasattr(obj, 'computed'))   # True (property)
print(hasattr(obj, 'dynamic'))    # True (setattr)
print(hasattr(obj, 'missing'))    # False

This shows hasattr working with different attribute types. It detects regular attributes, properties, and dynamically added attributes.

Properties are treated like regular attributes, demonstrating Python's uniform attribute access principle.

Error Handling

While hasattr is designed to prevent AttributeError, it can't catch all attribute-related issues. This example shows edge cases.

errors.py
class Problematic:
    def __init__(self):
        self._value = 10
    
    @property
    def value(self):
        return self._value
    
    @value.setter
    def value(self, val):
        if val < 0:
            raise ValueError("Must be positive")
        self._value = val
    
    def method(self):
        raise RuntimeError("Intentional error")

obj = Problematic()

# hasattr catches AttributeError but not other exceptions
print(hasattr(obj, 'missing'))  # False (safe)
print(hasattr(obj, 'value'))    # True (property exists)

# But property getter/setter errors still occur during access
try:
    obj.value = -5
except ValueError as e:
    print(f"Caught: {e}")

# Methods that raise errors still show as existing
print(hasattr(obj, 'method'))  # True (method exists)

hasattr only checks for attribute existence, not whether the attribute can be successfully accessed. Property setters and methods may still raise exceptions.

This demonstrates that hasattr is not a complete validation tool, but rather an existence checker.

Practical Use Case: Plugin System

A common use for hasattr is checking for optional features or plugins in a modular system. This example shows a simple plugin check.

plugins.py
class BasicViewer:
    def show(self, content):
        print(f"Basic: {content}")

class AdvancedViewer(BasicViewer):
    def show(self, content):
        print(f"Advanced: {content}")
    
    def save(self, content, filename):
        with open(filename, 'w') as f:
            f.write(content)

def process_content(viewer, content, filename=None):
    viewer.show(content)
    
    if hasattr(viewer, 'save') and filename:
        print("Saving content...")
        viewer.save(content, filename)
    else:
        print("Save feature not available")

basic = BasicViewer()
advanced = AdvancedViewer()

process_content(basic, "Hello")  # Basic only
process_content(advanced, "Hello", "output.txt")  # Uses save

This demonstrates using hasattr to check for optional features. The system works with both basic and advanced viewers without type checking.

This duck-typing approach is more flexible than explicit type checks and follows Python's EAFP (Easier to Ask for Forgiveness than Permission) principle.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.