Ich würde es vorziehen, in den meisten Fällen weder das eine noch das andere zu verwenden. Das Problem mit Eigenschaften ist, dass sie die Klasse weniger transparent machen. Dies ist vor allem dann ein Problem, wenn Sie eine Ausnahme von einem Setter auslösen würden. Zum Beispiel, wenn Sie eine Eigenschaft Account.email haben:
class Account(object):
@property
def email(self):
return self._email
@email.setter
def email(self, value):
if '@' not in value:
raise ValueError('Invalid email address.')
self._email = value
dann erwartet der Benutzer der Klasse nicht, dass die Zuweisung eines Wertes zu der Eigenschaft eine Ausnahme verursachen könnte:
a = Account()
a.email = 'badaddress'
--> ValueError: Invalid email address.
Infolgedessen kann die Ausnahme unbehandelt bleiben und sich entweder zu weit oben in der Aufrufkette ausbreiten, um ordnungsgemäß behandelt zu werden, oder zu einem sehr wenig hilfreichen Traceback führen, der dem Programmbenutzer präsentiert wird (was in der Welt von Python und Java leider allzu häufig vorkommt).
Ich würde auch die Verwendung von Gettern und Settern vermeiden:
- weil es sehr zeitaufwändig ist, sie für alle Eigenschaften im Voraus festzulegen,
- macht den Code unnötig länger, was das Verständnis und die Pflege des Codes erschwert,
- wenn man sie nur bei Bedarf für Eigenschaften definieren würde, würde sich die Schnittstelle der Klasse ändern, was allen Benutzern der Klasse schaden würde
Anstelle von Eigenschaften und Gettern/Settern ziehe ich es vor, die komplexe Logik an gut definierten Stellen, z. B. in einer Validierungsmethode, auszuführen:
class Account(object):
...
def validate(self):
if '@' not in self.email:
raise ValueError('Invalid email address.')
oder eine ähnliche Account.save-Methode.
Ich will damit nicht sagen, dass es keine Fälle gibt, in denen Eigenschaften nützlich sind, sondern nur, dass Sie besser dran sind, wenn Sie Ihre Klassen so einfach und transparent gestalten können, dass Sie sie nicht brauchen.