Utilisation des fonctions getattr() et setattr()
Python fournit des fonctions intégrées pour accéder et modifier dynamiquement les attributs d'un objet. Celles-ci sont particulièrement utiles lorsque vous souhaitez travailler avec des noms d'attributs qui ne sont pas connus avant l'exécution.
La fonction getattr()
La fonction getattr() vous permet d'accéder à un attribut en utilisant son nom sous forme de chaîne de caractères. La syntaxe est :
getattr(object, attribute_name, default_value)
object : L'objet dont vous souhaitez accéder à l'attribut
attribute_name : Une chaîne de caractères contenant le nom de l'attribut
default_value : Une valeur optionnelle à retourner si l'attribut n'existe pas
Créons un nouveau fichier appelé dynamic_attributes.py dans le répertoire /home/labex/project :
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}")
Exécutez ce code :
python3 /home/labex/project/dynamic_attributes.py
Vous devriez voir :
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.
Notez que pour l'attribut address, qui n'existe pas, getattr() renvoie notre valeur par défaut "Not available" au lieu de générer une erreur.
La fonction setattr()
La fonction setattr() vous permet de définir un attribut en utilisant son nom sous forme de chaîne de caractères. La syntaxe est :
setattr(object, attribute_name, value)
object : L'objet dont vous souhaitez définir l'attribut
attribute_name : Une chaîne de caractères contenant le nom de l'attribut
value : La valeur à affecter à l'attribut
Modifions notre fichier dynamic_attributes.py pour inclure des exemples d'utilisation de 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}")
Exécutez le code mis à jour :
python3 /home/labex/project/dynamic_attributes.py
Vous devriez voir :
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
Notez que nous avons pu modifier les attributs existants et également ajouter un attribut complètement nouveau (address) qui n'était pas défini dans la classe.
Exemple pratique
Créons un exemple plus pratique où l'accès et la modification dynamiques des attributs sont utiles. Créez un fichier appelé data_processor.py dans le répertoire /home/labex/project :
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}")
Exécutez ce code :
python3 /home/labex/project/data_processor.py
Vous devriez voir :
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
Cet exemple montre comment vous pouvez convertir des données d'un dictionnaire (qui peuvent provenir d'une base de données, d'une API ou d'un fichier) en un objet, puis accéder ou modifier ses attributs dynamiquement.