Cas d'utilisation pratiques
class Employee:
def __init__(self, salary):
self._salary = salary
@property
def salary(self):
return self._salary
@salary.setter
def salary(self, value):
if not isinstance(value, (int, float)):
raise TypeError("Salary must be a number")
if value < 0:
raise ValueError("Salary cannot be negative")
self._salary = round(value, 2)
Chargement paresseux (lazy loading) et mise en cache
class DatabaseConnection:
def __init__(self, connection_string):
self._connection_string = connection_string
self._connection = None
@property
def connection(self):
if self._connection is None:
self._connection = self._establish_connection()
return self._connection
def _establish_connection(self):
## Simulate expensive connection process
return f"Connected to {self._connection_string}"
Attributs en lecture seule
class ImmutableConfig:
def __init__(self, config_dict):
self._config = config_dict
@property
def database_host(self):
return self._config.get('database_host')
@property
def database_port(self):
return self._config.get('database_port')
Scénarios de cas d'utilisation
Scénario |
Avantage de la propriété |
Exemple |
Validation d'entrée |
Empêcher les données invalides |
Vérification de l'âge |
Valeurs calculées |
Calculs dynamiques |
Aire de formes géométriques |
Contrôle d'accès |
Restreindre les modifications directes |
Protection de données sensibles |
Journalisation et surveillance
class SensorData:
def __init__(self):
self._temperature = 0
@property
def temperature(self):
return self._temperature
@temperature.setter
def temperature(self, value):
print(f"Temperature changed: {self._temperature} -> {value}")
self._temperature = value
Gestion des dépendances de propriétés
class Rectangle:
def __init__(self, width, height):
self._width = width
self._height = height
@property
def width(self):
return self._width
@width.setter
def width(self, value):
self._width = value
## Trigger potential recalculations
self._update_derived_properties()
@property
def area(self):
return self._width * self._height
def _update_derived_properties(self):
## Additional logic for dependent properties
pass
Workflow de création de propriétés
graph TD
A[Identifier le besoin d'attribut] --> B{Besoins de logique personnalisée?}
B -->|Oui| C[Définir les méthodes de propriété]
B -->|Non| D[Utiliser un attribut standard]
C --> E[Implémenter le Getter/Setter]
E --> F[Ajouter la validation/transformation]
Recommandation de LabEx
Chez LabEx, nous insistons sur l'utilisation de propriétés dynamiques pour créer des classes plus intelligentes et autonomes qui encapsulent une logique complexe tout en conservant un code propre et lisible.
Composition avancée
class User:
def __init__(self, first_name, last_name):
self._first_name = first_name
self._last_name = last_name
@property
def full_name(self):
return f"{self._first_name} {self._last_name}"
@full_name.setter
def full_name(self, name):
self._first_name, self._last_name = name.split(' ', 1)