Klassen, die von eingebauten Klassen, deren einfachste object ist, abgeleitet werden, sind seit Python 2.2.3 sogenannte new-style-Klassen. Diese haben gegenüber "alten" Klassen ein paar Unterschiede:
Grundlegendes Verhalten
Sei instanz eine Instanz einer New-Style-Klasse A. type(instanz) ist nun das gleiche wie instanz.__class__, nämlich A.
Bei alten Klassen ist type(instanz) immer der gleiche Typ, nämlich types.InstanceType.
type(A) ist bei neuen Klassen übrigens type; bei alten war dies types.ClassType. Code, der nur mit types.ClassType und types.InstanceType arbeitet, muss also dringend aktualisiert werden!
Properties
Properties definieren Attribute, die es erlauben, beim Lesen und Setzen beliebigen Code auszuführen. Bei alten Klassen mussten dafür die Spezialmethoden __getattr__ und __setattr__ redefiniert werden, was fehleranfällig und unschön ist.
1 class RGB(object):
2 def _get_ri(self):
3 return int(self.r * 255)
4 def _set_ri(self, value)
5 self.r = float(value) / 255.0
6 ri = property(_get_ri, _set_ri, doc="set/get red as Integer 0-255")
7
8 def _get_gi(self):
9 return int(self.g * 255)
10 def _set_gi(self, value)
11 self.g = float(value) / 255.0
12 gi = property(_get_gi, _set_gi, doc="set/get green as Integer 0-255")
13
14 def _get_bi(self):
15 return int(self.b * 255)
16 def _set_bi(self, value)
17 self.b = float(value) / 255.0
18 bi = property(_get_bi, _set_bi, doc="set/get blue as Integer 0-255")
19
20 def __init__(self, red=0.0, green=0.0, blue=0.0)
21 if type(red) is float:
22 self.r = red
23 else:
24 self.ri = red
25 if type(green) is float:
26 self.g = green
27 else:
28 self.gi = green
29 if type(blue) is float:
30 self.b = blue
31 else:
32 self.bi = blue
33
34 def __str__(self):
35 return "#%02x%02x%02x" % (self.ri, self.gi, self.bi)
36
37 color = RGB(0.5, 127, 0)
38 print color
Properties sind übrigens sogenannte Deskriptoren.
Slots
Normalerweise werden bei Instanzen von Klassen (ob alt oder neu) alle Attribute in dem Dictionary self.__dict__ vorgehalten. Bei Klassen mit nur wenigen Attributen und gleichzeitig sehr großer Zahl von Instanzen kann der Speicherbedarf dabei zu groß werden. Wird dagegen, wie im Beispiel unten, eine Liste __slots__ definiert, so wird das Anlegen des Dictionarys __dict__ verhindert, und die einzelnen Attribute bekommen "direkt" einen Platz in der dem Objekt zugrundeliegenden C-Struktur. Nachteil: Wenn in der Klasse __slots__ definiert ist, so können nur Attribute geschrieben oder gelesen werden, deren Name in der Liste aufgeführt werden. Es können also nicht, wie es bei herkömmlichen Klassen möglich ist, zur Laufzeit Attribute mit einem neuen Namen einer Instanz der Klasse zugewiesen werden.
1 class NoSlots(object):
2 def __init__(self):
3 self.a = 1
4 self.b = 2
5 self.c = 3
6
7 class Slots(object):
8 __slots__ = ["a", "b", "c"]
9 def __init__(self):
10 self.a = 1
11 self.b = 2
12 self.c = 3
13
14 oldobj = NoSlots()
15 oldobj.d = 4 # funktioniert
16
17 newobj = Slots()
18 newobj.d = 4 # gibt eine Fehlermeldung
Vorsicht: Der oben genannte Nachteil wird häufig als Feature missverstanden. Einzig und allein der geringere Speicherbedarf ist Aufgabe von __slots__. Sinnvoll ist die Anwendung aber nur bei einer wirklich sehr großen Instanzenanzahl.
Eine detaillierte Beschreibung der Änderungen am Klassensystem gibt es unter http://www.python.org/2.2.3/descrintro.html.
Teilweise entnommen aus dem Beitrag New-style Klassen - eine Einführung