Using getattr() and setattr() Functions
Python provides built-in functions to access and modify object attributes dynamically. These are particularly useful when you want to work with attribute names that are not known until runtime.
The getattr() Function
The getattr()
function allows you to access an attribute using its name as a string. The syntax is:
getattr(object, attribute_name, default_value)
object
: The object whose attribute you want to access
attribute_name
: A string containing the name of the attribute
default_value
: An optional value to return if the attribute does not exist
Let us create a new file called dynamic_attributes.py
in the /home/labex/project
directory:
class Person:
def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job
def greet(self):
return f"Hello, my name is {self.name} and I am {self.age} years old."
## Create a Person object
john = Person("John", 30, "Developer")
## List of attributes to access
attributes = ["name", "age", "job", "address"]
## Access attributes using getattr()
print("Accessing attributes using getattr():")
for attr in attributes:
## The third parameter is the default value if the attribute doesn't exist
value = getattr(john, attr, "Not available")
print(f"{attr.capitalize()}: {value}")
## Call a method using getattr
greet_method = getattr(john, "greet")
greeting = greet_method()
print(f"Greeting: {greeting}")
Run this code:
python3 /home/labex/project/dynamic_attributes.py
You should see:
Accessing attributes using getattr():
Name: John
Age: 30
Job: Developer
Address: Not available
Greeting: Hello, my name is John and I am 30 years old.
Notice that for the address
attribute, which does not exist, getattr()
returns our default value "Not available" instead of raising an error.
The setattr() Function
The setattr()
function allows you to set an attribute using its name as a string. The syntax is:
setattr(object, attribute_name, value)
object
: The object whose attribute you want to set
attribute_name
: A string containing the name of the attribute
value
: The value to assign to the attribute
Let us modify our dynamic_attributes.py
file to include examples of using setattr()
:
class Person:
def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job
def greet(self):
return f"Hello, my name is {self.name} and I am {self.age} years old."
## Create a Person object
john = Person("John", 30, "Developer")
print("Original attributes:")
print(f"Name: {john.name}")
print(f"Age: {john.age}")
print(f"Job: {john.job}")
## Modify attributes using setattr()
print("\nModifying attributes using setattr():")
setattr(john, "name", "John Smith")
setattr(john, "age", 31)
setattr(john, "job", "Senior Developer")
## Add a new attribute using setattr()
setattr(john, "address", "123 Main St")
## Print the modified attributes
print("\nModified attributes:")
print(f"Name: {john.name}")
print(f"Age: {john.age}")
print(f"Job: {john.job}")
print(f"Address: {john.address}")
## Access attributes using getattr()
print("\nAccessing attributes using getattr():")
for attr in ["name", "age", "job", "address"]:
value = getattr(john, attr, "Not available")
print(f"{attr.capitalize()}: {value}")
Run the updated code:
python3 /home/labex/project/dynamic_attributes.py
You should see:
Original attributes:
Name: John
Age: 30
Job: Developer
Modifying attributes using setattr():
Modified attributes:
Name: John Smith
Age: 31
Job: Senior Developer
Address: 123 Main St
Accessing attributes using getattr():
Name: John Smith
Age: 31
Job: Senior Developer
Address: 123 Main St
Notice that we were able to modify existing attributes and also add a completely new attribute (address
) that was not defined in the class.
Practical Example
Let us create a more practical example where dynamic attribute access and modification are useful. Create a file called data_processor.py
in the /home/labex/project
directory:
class DataRecord:
def __init__(self):
## Start with no attributes
pass
## Create a function to process a dictionary into an object
def dict_to_object(data_dict):
record = DataRecord()
for key, value in data_dict.items():
setattr(record, key, value)
return record
## Sample data (could come from a database, API, etc.)
user_data = {
"user_id": 12345,
"username": "johndoe",
"email": "john@example.com",
"active": True,
"login_count": 27
}
## Convert the dictionary to an object
user = dict_to_object(user_data)
## Access the attributes
print(f"User ID: {user.user_id}")
print(f"Username: {user.username}")
print(f"Email: {user.email}")
print(f"Active: {user.active}")
print(f"Login Count: {user.login_count}")
## We can also add or modify attributes
setattr(user, "last_login", "2023-09-15")
setattr(user, "login_count", 28)
print("\nAfter modifications:")
print(f"Login Count: {user.login_count}")
print(f"Last Login: {user.last_login}")
## We can also access all attributes dynamically
print("\nAll attributes:")
for attr in ["user_id", "username", "email", "active", "login_count", "last_login"]:
value = getattr(user, attr, None)
print(f"{attr}: {value}")
Run this code:
python3 /home/labex/project/data_processor.py
You should see:
User ID: 12345
Username: johndoe
Email: john@example.com
Active: True
Login Count: 27
After modifications:
Login Count: 28
Last Login: 2023-09-15
All attributes:
user_id: 12345
username: johndoe
email: john@example.com
active: True
login_count: 28
last_login: 2023-09-15
This example shows how you can convert data from a dictionary (which might come from a database, API, or file) into an object, and then access or modify its attributes dynamically.