@pütone: `__new__` braucht man, wenn man den "echten" Konstruktor von "immutable"s überschreiben möchte. Völlig sinnloses Beispiel:
Code: Alles auswählen
def MyInt(int):
def __init__(self, value):
int.__init__(self, 2 * value) # Geht nicht!
Zu dem Zeitpunkt wo die `__init__()` aufgerufen wird, existiert das Objekt schon und man kann den Wert nicht mehr ändern. Dafür muss man `__new__()` überschreiben. Und das ist ein echter Konstruktor in dem Sinne, das man dort wirklich ein Objekt erzeugen kann und zurückgeben muss.
Andere Einsatzzwecke sind "Singletons", oder das "Flyweight"-Entwurfsmuster.
Properties sind dazu da um aus einfachen Attributen noch nachträglich "berechnete Attribute" machen zu können, ohne das sich die API ändert. Dieses Bankkonto-Beispiel ist IMHO irreführend, weil damit suggeriert wird, dass man natürlich nicht möchte, dass jemand von aussen den Kontostand ändern kann. Nur das man in einem Programm, das diese Objekte verwendet, ja gar nicht von aussen kommt! Die Kapselung ist nicht zum Schutz der Daten da, sondern um Flexibilität bei der Implementierung der Interna zu waren. Wenn der Räuber Hotzenplotz aus dem Buch in der Lage ist beliebige Konto-Objekte zu erstellen, dann ist aus Sicherheitsaspekten eh alles zu spät. Dann kann er sich auch ein neues Konto erzeugen und alles von den anderen dorthin überweisen, auch wenn er keinen direkten Zugriff auf das Attribut `__Kontostand` hat.
Ein Unterstrich in `_kontostand` sollte reichen, damit keiner auf die Idee kommt von aussen direkt darauf zuzugreifen, ohne zu wissen was er da tut.
Statische Methoden sind vom Verhalten her einfach nur Funktionen, die im Namensraum einer Klasse stecken. Klassenmethoden bekommen als erstes Argument automatisch die Klasse als Argument auf der sie aufgerufen werden. Also ein ähnlich "magisches" Argument wie `self` bei normalen Methoden. Beispiel:
Code: Alles auswählen
class A(object):
def __init__(self, arg):
print 'init A', arg
@classmethod
def blub(cls, arg):
return cls(arg)
class B(A):
def __init__(self, arg):
print 'init B', arg
A.__init__(self, arg)
def main():
x = B.blub(42)
print type(x)