Python hasattr Function

Complete guide to Python's hasattr function covering object introspection, attribute checking, and practical examples.

Python hasattr Function

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

  • Prefer over try/except: Use hasattr for simple existence checks

  • Document expected attributes: Clearly document interfaces

  • Consider properties: Remember hasattr checks existence, not usability

  • Use with duck typing: Check capabilities rather than types

  • Avoid overuse: Sometimes direct access with try/except is clearer

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.

ad ad