getattr() is a built-in Python function that reads an attribute from an object by name. It is most useful when the attribute name is known at runtime instead of being written directly with dot notation.
The basic form is getattr(object, name). The optional third argument is a default value returned when the attribute does not exist. Without that default, Python raises AttributeError.
The official Python getattr documentation defines the built-in function, and the official hasattr documentation explains the related existence check. Related PythonPool guides cover setattr, vars, callable, checking object attributes, and inspect.
Read An Attribute By Name
Dot notation is best when the attribute name is fixed in the source code. getattr() is best when the name comes from configuration, a column choice, or another runtime decision.
class User:
def __init__(self, name, role):
self.name = name
self.role = role
user = User("Maya", "admin")
print(getattr(user, "name"))
print(getattr(user, "role"))
This produces the same values as user.name and user.role, but the attribute name is passed as a string.
Use dot notation when possible because it is easier for readers and tools to follow. Reach for getattr() when the code genuinely needs a dynamic name.
Provide A Default Value
The third argument prevents AttributeError when an optional attribute is missing.
class Profile:
def __init__(self, username):
self.username = username
profile = Profile("nora")
print(getattr(profile, "username", "unknown"))
print(getattr(profile, "email", "not provided"))
The default should be a value the rest of the code can handle. Common defaults include None, an empty string, a sentinel object, or a domain-specific fallback.
Do not use a default to hide a real bug. If an attribute should always exist, let the exception reveal the broken object.
Select Fields Dynamically
getattr() is useful for selecting one attribute from an allowed set of names.
class Article:
def __init__(self, title, views):
self.title = title
self.views = views
article = Article("Python getattr", 1200)
field = "views"
if field in {"title", "views"}:
print(getattr(article, field))
The allowlist matters. Do not pass untrusted names directly into getattr() and then act on the result without checking what names are allowed.
This pattern works well for sorting, display columns, export choices, and small command handlers where the accepted names are known.
Call A Method By Name
If the attribute is a method, getattr() returns a callable object. You can then check it and call it.
class Greeter:
def hello(self):
return "hello"
def goodbye(self):
return "goodbye"
greeter = Greeter()
action = "hello"
method = getattr(greeter, action)
if callable(method):
print(method())
This is a compact dispatch pattern, but it should still use an allowlist for names that come from outside the program.
For public commands, a dictionary that maps command names to functions is often clearer. Use getattr() when the object model is already the right source of behavior.
Compare getattr And hasattr
hasattr() answers whether an attribute can be read. getattr() reads it. A sentinel default can do both in one lookup.
class Settings:
timeout = 30
settings = Settings()
missing = object()
value = getattr(settings, "timeout", missing)
if value is missing:
print("missing")
else:
print(value)
The sentinel approach distinguishes a missing attribute from a real value such as None, 0, or an empty string.
Use hasattr() when you only need a yes-or-no answer. Use getattr() when you need the value itself.
Avoid Unsafe Lookup
Dynamic lookup can expose attributes that were never meant to be commands. Keep accepted names explicit.
class Report:
def summary(self):
return "summary ready"
def delete(self):
return "not allowed here"
report = Report()
actions = {"summary"}
requested = "summary"
if requested in actions:
print(getattr(report, requested)())
This keeps the dynamic behavior narrow. Without the allowlist, a caller might reach methods that should not be available in that context.
Know When Not To Use It
getattr() is powerful, but it can make code harder to trace when used for ordinary attribute access. If the name is fixed and clear, user.name is better than getattr(user, "name").
Static analysis tools, autocomplete, and readers all understand dot notation more easily. Heavy dynamic lookup can hide spelling mistakes until runtime and make refactoring more fragile.
Be especially careful with broad exception handling. Catching AttributeError around a large block can hide errors raised inside property methods. Prefer a default argument, a small lookup, or a sentinel when the missing attribute is expected.
Properties can also run code when accessed. Calling getattr() on a property is not just reading stored data; it may perform calculation, validation, or I/O depending on how the class was written. Treat dynamic property access with the same care as direct property access.
For dictionaries, use normal key access or dict.get(). getattr() reads object attributes, not dictionary keys, so it is the wrong tool for plain mapping data unless the object intentionally exposes attributes.
Readable code should stay the priority.
The practical rule is to prefer dot notation for fixed attributes, use getattr() for runtime names, supply a default only when missing attributes are expected, and validate names before calling methods dynamically.