Maintenant que nous avons exploré diverses applications de l'attribut __dict__
, mettons nos connaissances en pratique en créant une simple application de gestionnaire de contacts. Ce mini-projet démontrera comment utiliser __dict__
dans un scénario réel.
Notre gestionnaire de contacts nous permettra de :
- Ajouter des contacts avec divers attributs
- Rechercher des contacts
- Mettre à jour les informations de contact
- Supprimer des contacts
- Exporter les contacts en JSON
- Importer les contacts depuis JSON
- Créez un nouveau fichier nommé
contact_manager.py
:
import json
import os
class Contact:
def __init__(self, name, email=None, phone=None, **kwargs):
self.name = name
self.email = email
self.phone = phone
## Add any additional attributes
for key, value in kwargs.items():
self.__dict__[key] = value
def update(self, **kwargs):
"""Update contact attributes"""
self.__dict__.update(kwargs)
def __str__(self):
"""String representation of the contact"""
attrs = []
for key, value in self.__dict__.items():
if value is not None:
attrs.append(f"{key}: {value}")
return ", ".join(attrs)
class ContactManager:
def __init__(self):
self.contacts = []
def add_contact(self, contact):
"""Add a new contact"""
self.contacts.append(contact)
print(f"Added contact: {contact.name}")
def find_contact(self, **kwargs):
"""Find contacts matching the criteria"""
results = []
for contact in self.contacts:
match = True
for key, value in kwargs.items():
## Skip if the contact doesn't have this attribute
if key not in contact.__dict__:
match = False
break
## Skip if the attribute value doesn't match
if contact.__dict__[key] != value:
match = False
break
if match:
results.append(contact)
return results
def update_contact(self, contact, **kwargs):
"""Update a contact's attributes"""
contact.update(**kwargs)
print(f"Updated contact: {contact.name}")
def delete_contact(self, contact):
"""Delete a contact"""
if contact in self.contacts:
self.contacts.remove(contact)
print(f"Deleted contact: {contact.name}")
else:
print("Contact not found.")
def export_contacts(self, filename):
"""Export contacts to a JSON file"""
contacts_data = []
for contact in self.contacts:
contacts_data.append(contact.__dict__)
with open(filename, 'w') as f:
json.dump(contacts_data, f, indent=2)
print(f"Exported {len(self.contacts)} contacts to {filename}")
def import_contacts(self, filename):
"""Import contacts from a JSON file"""
if not os.path.exists(filename):
print(f"File {filename} not found.")
return
with open(filename, 'r') as f:
contacts_data = json.load(f)
imported_count = 0
for data in contacts_data:
## Create a copy of the data to avoid modifying the original
contact_data = data.copy()
## Get the required parameters
name = contact_data.pop('name', None)
email = contact_data.pop('email', None)
phone = contact_data.pop('phone', None)
if name:
## Create a new contact with remaining attributes as kwargs
contact = Contact(name, email, phone, **contact_data)
self.contacts.append(contact)
imported_count += 1
print(f"Imported {imported_count} contacts from {filename}")
def print_all_contacts(self):
"""Print all contacts"""
if not self.contacts:
print("No contacts found.")
return
print(f"\nAll Contacts ({len(self.contacts)}):")
print("-" * 40)
for i, contact in enumerate(self.contacts, 1):
print(f"{i}. {contact}")
print("-" * 40)
## Let's test our contact manager
if __name__ == "__main__":
## Create a contact manager
manager = ContactManager()
## Add some contacts
manager.add_contact(Contact("John Doe", "[email protected]", "555-1234",
address="123 Main St", city="Boston"))
manager.add_contact(Contact("Jane Smith", "[email protected]", "555-5678",
company="ABC Corp", role="Developer"))
manager.add_contact(Contact("Bob Johnson", "[email protected]", "555-9012",
twitter="@bobjohnson", birthday="1985-03-15"))
## Print all contacts
manager.print_all_contacts()
## Find contacts
print("\nContacts with email ending with @example.com:")
for contact in manager.contacts:
if contact.email and contact.email.endswith("@example.com"):
print(f"- {contact.name}: {contact.email}")
## Use the find_contact method
print("\nFinding contacts by name:")
results = manager.find_contact(name="Jane Smith")
for contact in results:
print(f"Found: {contact}")
## Update a contact
if results:
manager.update_contact(results[0], phone="555-NEW-NUM", role="Senior Developer")
print(f"After update: {results[0]}")
## Export contacts to JSON
manager.export_contacts("contacts.json")
## Delete a contact
manager.delete_contact(results[0])
## Print all contacts after deletion
manager.print_all_contacts()
## Create a new manager and import contacts
print("\nCreating a new manager and importing contacts:")
new_manager = ContactManager()
new_manager.import_contacts("contacts.json")
new_manager.print_all_contacts()
- Exécutez le fichier :
python3 contact_manager.py
Vous devriez voir une sortie montrant le gestionnaire de contacts en action, y compris l'ajout, la recherche, la mise à jour et la suppression de contacts, ainsi que l'exportation et l'importation de contacts vers et depuis un fichier JSON.
Maintenant, améliorons notre gestionnaire de contacts en ajoutant la possibilité d'ajouter des champs personnalisés pour différents types de contacts :
- Créez un nouveau fichier nommé
extended_contact_manager.py
:
from contact_manager import Contact, ContactManager
class BusinessContact(Contact):
def __init__(self, name, email=None, phone=None, company=None, role=None, **kwargs):
super().__init__(name, email, phone, **kwargs)
self.company = company
self.role = role
self.contact_type = "business"
class PersonalContact(Contact):
def __init__(self, name, email=None, phone=None, relationship=None, birthday=None, **kwargs):
super().__init__(name, email, phone, **kwargs)
self.relationship = relationship
self.birthday = birthday
self.contact_type = "personal"
class ExtendedContactManager(ContactManager):
def add_business_contact(self, name, email=None, phone=None, company=None, role=None, **kwargs):
contact = BusinessContact(name, email, phone, company, role, **kwargs)
self.add_contact(contact)
return contact
def add_personal_contact(self, name, email=None, phone=None, relationship=None, birthday=None, **kwargs):
contact = PersonalContact(name, email, phone, relationship, birthday, **kwargs)
self.add_contact(contact)
return contact
def find_by_contact_type(self, contact_type):
"""Find contacts by type (business or personal)"""
return self.find_contact(contact_type=contact_type)
def get_contact_details(self, contact):
"""Get detailed information about a contact"""
details = []
for key, value in contact.__dict__.items():
if value is not None:
if key == "contact_type":
details.append(f"Type: {value.capitalize()}")
else:
## Convert key from snake_case to Title Case
formatted_key = " ".join(word.capitalize() for word in key.split("_"))
details.append(f"{formatted_key}: {value}")
return "\n".join(details)
## Test the extended contact manager
if __name__ == "__main__":
## Create an extended contact manager
manager = ExtendedContactManager()
## Add some business contacts
manager.add_business_contact(
"Alice Johnson",
"[email protected]",
"555-1111",
"XYZ Corp",
"Marketing Manager",
department="Marketing",
office_location="Building A, 3rd Floor"
)
manager.add_business_contact(
"Bob Williams",
"[email protected]",
"555-2222",
"StartUp Inc",
"CEO",
linkedin="linkedin.com/in/bobwilliams"
)
## Add some personal contacts
manager.add_personal_contact(
"Carol Davis",
"[email protected]",
"555-3333",
"Friend",
"1990-05-15",
address="456 Oak St",
favorite_restaurant="Italian Place"
)
manager.add_personal_contact(
"Dave Wilson",
"[email protected]",
"555-4444",
"Family",
"1982-12-03",
emergency_contact=True
)
## Print all contacts
manager.print_all_contacts()
## Find contacts by type
print("\nBusiness Contacts:")
business_contacts = manager.find_by_contact_type("business")
for contact in business_contacts:
print(f"- {contact.name} ({contact.company})")
print("\nPersonal Contacts:")
personal_contacts = manager.find_by_contact_type("personal")
for contact in personal_contacts:
print(f"- {contact.name} ({contact.relationship})")
## Show detailed information for a contact
if business_contacts:
print("\nDetailed information for", business_contacts[0].name)
print(manager.get_contact_details(business_contacts[0]))
## Export contacts to JSON
manager.export_contacts("extended_contacts.json")
## Import contacts
new_manager = ExtendedContactManager()
new_manager.import_contacts("extended_contacts.json")
print("\nAfter importing:")
new_manager.print_all_contacts()
## Check if we can still identify contact types after import
imported_business = new_manager.find_by_contact_type("business")
print(f"\nImported {len(imported_business)} business contacts")
imported_personal = new_manager.find_by_contact_type("personal")
print(f"Imported {len(imported_personal)} personal contacts")
- Exécutez le fichier :
python3 extended_contact_manager.py
Ce gestionnaire de contacts étendu montre comment nous pouvons utiliser l'attribut __dict__
pour créer des structures de données flexibles capables de gérer différents types de contacts avec des attributs variables.
Étape 3 : Créer une simple interface en ligne de commande
Enfin, créons une simple interface en ligne de commande pour notre gestionnaire de contacts :
- Créez un nouveau fichier nommé
contact_manager_cli.py
:
from extended_contact_manager import ExtendedContactManager, BusinessContact, PersonalContact
def print_menu():
print("\n===== Contact Manager =====")
print("1. Add Business Contact")
print("2. Add Personal Contact")
print("3. List All Contacts")
print("4. Find Contact")
print("5. Update Contact")
print("6. Delete Contact")
print("7. Export Contacts")
print("8. Import Contacts")
print("9. Exit")
print("==========================")
def get_contact_details(contact_type):
"""Get contact details from user input"""
details = {}
## Common fields
details['name'] = input("Name: ")
details['email'] = input("Email (optional): ") or None
details['phone'] = input("Phone (optional): ") or None
## Type-specific fields
if contact_type == "business":
details['company'] = input("Company (optional): ") or None
details['role'] = input("Role (optional): ") or None
## Ask for custom fields
print("Add custom fields (leave empty to finish):")
while True:
field_name = input("Field name (or empty to finish): ")
if not field_name:
break
field_value = input(f"{field_name}: ")
details[field_name] = field_value
elif contact_type == "personal":
details['relationship'] = input("Relationship (optional): ") or None
details['birthday'] = input("Birthday (YYYY-MM-DD, optional): ") or None
## Ask for custom fields
print("Add custom fields (leave empty to finish):")
while True:
field_name = input("Field name (or empty to finish): ")
if not field_name:
break
field_value = input(f"{field_name}: ")
details[field_name] = field_value
return details
def select_contact(manager):
"""Let the user select a contact from the list"""
if not manager.contacts:
print("No contacts available.")
return None
print("\nSelect a contact:")
for i, contact in enumerate(manager.contacts, 1):
print(f"{i}. {contact.name}")
try:
selection = int(input("Enter number (0 to cancel): "))
if selection == 0:
return None
if 1 <= selection <= len(manager.contacts):
return manager.contacts[selection - 1]
else:
print("Invalid selection.")
return None
except ValueError:
print("Please enter a valid number.")
return None
def main():
manager = ExtendedContactManager()
while True:
print_menu()
choice = input("Enter your choice (1-9): ")
if choice == '1':
## Add Business Contact
print("\n-- Add Business Contact --")
details = get_contact_details("business")
name = details.pop('name')
email = details.pop('email')
phone = details.pop('phone')
company = details.pop('company')
role = details.pop('role')
manager.add_business_contact(name, email, phone, company, role, **details)
elif choice == '2':
## Add Personal Contact
print("\n-- Add Personal Contact --")
details = get_contact_details("personal")
name = details.pop('name')
email = details.pop('email')
phone = details.pop('phone')
relationship = details.pop('relationship')
birthday = details.pop('birthday')
manager.add_personal_contact(name, email, phone, relationship, birthday, **details)
elif choice == '3':
## List All Contacts
manager.print_all_contacts()
elif choice == '4':
## Find Contact
print("\n-- Find Contact --")
search_term = input("Enter name to search: ")
results = manager.find_contact(name=search_term)
if results:
print(f"\nFound {len(results)} contacts:")
for contact in results:
print(manager.get_contact_details(contact))
print("-" * 30)
else:
print("No contacts found with that name.")
elif choice == '5':
## Update Contact
print("\n-- Update Contact --")
contact = select_contact(manager)
if contact:
print("\nCurrent details:")
print(manager.get_contact_details(contact))
print("\nEnter new details (leave empty to keep current value):")
updates = {}
for key, value in contact.__dict__.items():
if key != "contact_type": ## Don't allow changing the contact type
new_value = input(f"{key} [{value}]: ")
if new_value and new_value != str(value):
updates[key] = new_value
manager.update_contact(contact, **updates)
print("\nContact updated.")
elif choice == '6':
## Delete Contact
print("\n-- Delete Contact --")
contact = select_contact(manager)
if contact:
confirm = input(f"Are you sure you want to delete {contact.name}? (y/n): ")
if confirm.lower() == 'y':
manager.delete_contact(contact)
elif choice == '7':
## Export Contacts
print("\n-- Export Contacts --")
filename = input("Enter filename (default: contacts.json): ") or "contacts.json"
manager.export_contacts(filename)
elif choice == '8':
## Import Contacts
print("\n-- Import Contacts --")
filename = input("Enter filename: ")
manager.import_contacts(filename)
elif choice == '9':
## Exit
print("\nThank you for using Contact Manager!")
break
else:
print("Invalid choice. Please try again.")
if __name__ == "__main__":
main()
- Exécutez l'application CLI :
python3 contact_manager_cli.py
- Essayez d'ajouter des contacts, de rechercher des contacts, de mettre à jour des contacts et d'exporter/importer des contacts à l'aide de l'interface en ligne de commande.
Ce mini-projet démontre à quel point l'attribut __dict__
peut être puissant lors de la création d'applications pilotées par les données et flexibles en Python. Le gestionnaire de contacts permet des champs personnalisés sur les contacts, la sérialisation vers et depuis JSON, et une gestion facile des différents types de contacts, en tirant tous parti de l'attribut __dict__
pour gérer dynamiquement les données d'instance.
Grâce à ce projet, vous avez appris à :
- Utiliser
__dict__
pour stocker et récupérer les attributs d'objets
- Créer des classes flexibles capables de gérer des attributs variables
- Sérialiser et désérialiser des objets vers et depuis JSON
- Créer une simple application en ligne de commande qui exploite les attributs dynamiques
Ces compétences peuvent être appliquées à de nombreuses applications Python réelles, des outils de traitement de données aux applications Web et aux intégrations d'API.