[Python-de] Definition von Klassen

Stefan Behnel behnel_ml at gkec.informatik.tu-darmstadt.de
Mon Apr 10 07:29:30 CEST 2006


Pascal Dreisbach schrieb:
> Ich bin gerade dabei, mir mit Hilfe von Python als Anfänger das 
> objektorientierte Programmieren etwas näher zu bringen.
> 
> Neben dem Lesen von Büchern und zahlreichen Online-Hilfen, probiere ich 
> mich an einem kleinen Server/Client Projekt.
> 
> Was ich aktuell nicht ganz verstehe, ist der Unterschied zwischen 
> folgenden zwei Definitionen:
> 
>  >>>
> class MyClass:
>      x=1
> 
>      def __init__(self):
>          pass
> <<<
>  >>>
> class MyClass:
> 
>      def __init__(self):
>          self.x=1
> <<<
> 
> Im ersten Fall wird x als Klassenattribut beschrieben, im zweiten Fall 
> soll es ein Objektattribut sein?
> 
> Aber kann nicht beides über
>  >>>
> klasse = MyClass()
> print klasse.x
> <<<
> angesprochen werden?

Ja, aber der wichtigste Unterschied liegt in der Benutzung. Im ersten Fall ist
 der Wert in der Klasse gespeichert, also für alle Instanzen der Klasse
identisch. Im zweiten Fall ist der Wert Teil der Instanzen, also unabhängig.

Also:

class Klassenhalter:
  x = 1

class Objekthalter:
  def __init__(self):
    self.x = 1

c1 = Klassenhalter()
c2 = Klassenhalter()
c1.x = 2
print c2.x

gibt dir 2 aus. Anders hier:

o1 = Objekthalter()
o2 = Objekthalter()
o1.x = 2
print o2.x

das gibt 1 aus und nicht 2. Wichtig ist, dass Instanzattribute (und Methoden)
Klassenattribute überschreiben. Stell dir einfach vor, dass die Klasse zuerst
da ist und alles, was in der Instanz hinzukommt, vorne angestellt wird, also
zuerst sichtbar ist. Der Zugriff auf Klassenattribute ist immer über diesen
Umweg möglich:

c1.__class__.x

denn c1.__class__ erlaubt dir den Zugriff auf die Klasse (oder, genauer
gesagt, das Klassenobjekt). Vielleicht verwirrt es dich, dass Klassen in
Python auch Objekte sind, eben Klassenobjekte, von denen Objektinstanzen
abgeleitet werden können. Aber das ist in den "wahren" OO-Sprachen eigentlich
immer der Fall. Alles ist ein Objekt.

Nebenbei bemerkt, eigentlich ist es sogar eine sehr schöne Eigenschaft von
Python, dass es keinen sichtbaren Unterschied zwischen der Verwendung von
Klassenobjekten, aufrufbaren Objekten (Stichwort __call__) und Funktionen
gibt. Du rufst sie auf und erhälst das Ergebnis zurück. Aber gut, danach war
ja eigentlich gar nicht gefragt...

Hoffe geholfen zu haben,
Stefan