\section {Typen und Objekte}
\label {typ-obj}

  \subsection {Definition Objekt}
  \label {objdef}

    Ein Objekt in Python zeichnet sich durch vier Eigenschaften\footnote
    {Entnommen aus \cite[Abschnitt~1]{typ-obj}} aus:

    \begin {itemize}
      \item Identität
      \item Attribute
      \item Namen und
      \item Beziehungen zu anderen Objekten.
    \end {itemize}

    \subsubsection {Identität} 
    
      Die Identität wird in der aktuellen Implementation durch die
      Speicheradresse des Objekts repräsentiert.  Zu einem gegebenen
      Zeitpunkt ist die Identität aller existierenden Objekte
      unterscheidbar.  Verschiedene Objekte, deren Lebenszeiträume sich
      nicht überschneiden, können dennoch die gleiche Identität im Sinne
      der Implementation besitzen.

    \subsubsection {Attribute} 
    
      Die Attribute eines Objekts sind Name-Wert-Paare. Auf den Wert
      eines Attributs \lstinline $attr$ eines Objekts mit dem Namen
      \lstinline $obj$ wird mit dem Punktoperator zugegriffen:
      \lstinline $obj.attr$.  Der Wert eines Attributs kann beliebigen
      Typs sein. Einem Attributnamen können nacheinander Werte
      verschiedener Typen zugewiesen werden, ohne eine Warnung oder
      einen Fehler zu erzeugen.  Existiert bei einer Zuweisung noch kein
      Attribut mit dem gegebenen Namen, wird es kommentarlos erzeugt.
      Der Abschnitt~\vref {att-meth} widmet sich den Details.

    \subsubsection {Namen} 
    
      Der Name ist die Zeichenkette, unter dem das Objekt im Programm
      angesprochen werden kann. In anderen Programmiersprachen spräche
      man vom Variablennamen.  Objekte haben oft mehrere Namen,
      eventuell aber auch gar keinen. Zum Beispiel kann eine Liste
      benannt sein, die enthaltenen Objekte haben aber keinen eigenen
      direkt sichtbaren Namen und existieren nur als deren Inhalt.

    \lstinputlisting[float=tb,caption=Objektbeziehungen,
      label=lst:beziehungen]{lst/relations.py}

    \subsubsection {Beziehungen}
    
      Python kennt zwei Arten der Beziehung von Objekten untereinander:
      Vererbung und Instanzierung. Beide haben die in objektorientierten
      Sprachen übliche Semantik. In Listing~\vref {lst:beziehungen}
      sehen wir ein Beispiel. Zu Beginn stehen zwei Klassendefinitionen:
      \lstinline $Bird$ und deren Unterklasse \lstinline $Duck$. In der
      Methode \lstinline $__init__$ werden zwei Instanzattribute
      definiert.  Diese Methode wird Python bei jeder Instanzierung
      einer \lstinline $Duck$ aufrufen. Der Parameter mit dem Namen
      \lstinline $self$ ist immer die neue Instanz selbst.  Beide
      Klassen implementieren die Methode \lstinline $talk$. Das Objekt
      \lstinline $donald$ ist eine Instanz der Klasse \lstinline $Duck$.
      Da \lstinline $Duck$ von \lstinline $Bird$ erbt, ist \lstinline
      $donald$ gleichzeitig eine Instanz von \lstinline $Bird$.  Die
      Attribute von \lstinline $Duck$ überdecken diejenigen von
      \lstinline $Bird$.  Attribute, die in \lstinline $Duck$ nicht
      vorhanden sind, werden von \lstinline $Bird$ geerbt.

      Zur Benutzung der eingebauten Funktionen\footnote {Für eine
      komplette Liste aller eingebauten Funktionen siehe
      \cite[Abschnitt~2.1, Built-In Functions]{pylib}.} \lstinline
      $issubclass$ und \lstinline $isinstance$ ist nebenbei noch zu
      bemerken, dass hier offenbar wird, dass Klassen \emph{first class
      objects} sind und deswegen als Parameter einer Funktion übergeben
      werden dürfen. Was Klassen von anderen Objekten unterscheidet, ist
      Gegenstand des Abschnitts~\ref {metaklassen}.

  \subsection {Typen und Klassen}

    Ursprünglich wurde in Python streng zwischen eingebauten Typen und
    vom Nutzer erstellten (oder aus Modulen importierten) Klassen
    unterschieden. Der Unterschied äußerte sich unter anderem darin,
    dass keine Unterklassen von Typen erstellt werden konnten. Als
    Workaround existieren noch heute Wrapperklassen wie \lstinline
    $UserDict$, die ein normales \lstinline $dict$ -- also einen Typ --
    kapseln, aber echte Klassen sind, von denen sich auch ableiten läßt.

    Erst seit Python 2.2 (aktuell: 2.4.3) verhalten sich die eingebauten
    Typen größtenteils wie selbst definierte Klassen.\footnote {Siehe
    \citep {unify} für die vollständige Dokumentation der
    Vereinheitlichung von Typen und Klassen.} Sie können aber weiterhin
    -- im Gegensatz zu eigenen Klassen -- nicht verändert werden.
    Operationen, die einem eingebauten Typ oder einer Instanz eines Typs
    Attribute zuweisen, erzeugen einen \lstinline $TypeError$. Das ist
    heute aber vermeidbar, weil direkt von (fast allen) eingebauten
    Typen abgeleitet werden kann.

    Aufgrund dieser Annäherung von Typen und Klassen werden beide
    Begriffe im Zusammenhang mit Python inzwischen häufig synonym
    verwendet. Will man die weiterhin bestehenden Unterschiede zwischen
    Typen und Klassen betonen, bleibt es jedoch sinnvoll, beide Begriffe
    zu unterscheiden. Ungeachtet dessen spricht man in Python immer vom
    \emph {Typ} eines Objekts, wenn man die Klasse meint, deren Instanz
    sie ist.

  \subsection {Classic und New-Style Classes}
  \label {properties-mentioned}

    Weiterhin wird seit Version 2.2 zwischen \emph {Classic Classes} und
    \emph {New-Style Classes} unterschieden.  New-Style Classes sind all
    diejenigen Klassen, die von \lstinline $object$ ableiten. Dazu
    zählen ab dieser Pythonversion alle eingebauten Typen und natürlich
    all diejenigen benutzerdefinierten Klassen, die in ihrer Definition
    \lstinline $object$ bzw. eine ihrer Unterklassen als Oberklasse
    angegeben haben. Klassen ohne \lstinline $object$ in ihrer
    Vererbungshierarchie heißen Classic Classes. New-Style Classes
    unterstützen einige neue Features, darunter \emph {Managed
    Attributes} und \lstinline $super$. 

    Managed Attributes (auch \emph {Properties} genannt) sind
    Objektattribute, die vom Benutzer des Objekts wie ein normales
    Attribut angesprochen werden, innerhalb des Objekts aber beliebige
    Methodenaufrufe auslösen. Sie ersetzen also ungefähr die in anderen
    Sprachen üblichen Attribute mit Getter- und Settermethoden.
    Abschnitt~\vref {properties} erläutert die genaue Funktionsweise von
    Properties.

    Die Funktion \lstinline $super$\footnote {Genau genommen sind
    \lstinline $property$ und \lstinline $super$ Typen, deren
    Konstruktor aufgerufen wird.} erleichtert den Aufruf von Methoden
    einer Oberklasse. Sie soll insbesondere bei kreisförmigen
    Vererbungshierarchien\footnote {Solche Hierarchien können in Python
    auftreten, da Mehrfachvererbung erlaubt ist.} eine Hilfe darstellen.
    Weitere Informationen hierzu befinden sich im bereits erwähnten
    \citep {unify}.

    Zukünftig ist damit zu rechnen, dass Classic Classes vollständig aus
    der Sprache verschwinden werden.\footnote {\citep [Core
    Language]{pep3100}} Der weitere Teil dieser Arbeit beschäftigt sich
    daher ausschließlich mit New-Style Classes.

  \subsection {Metaklassen}
  \label {metaklassen}
  % <type 'type'>, <type 'object'>

    \begin {figure}[tbp]
      \begin {center}
        \includegraphics[width=0.85\textwidth]{img/types_map}
      \end {center}
      \caption {Metaklassen, Klassen und Instanzen}
      \centering Quelle: \cite{typ-obj}
      \label {fig:types}
    \end {figure}

    Klassen sind Objekte und wie alle Objekte haben sie einen Typ.
    Klassen sind also selbst Instanzen einer Klasse, genauer gesagt
    einer sogenannten \emph {Metaklasse}. Metaklassen unterscheiden sich
    nur dadurch von normalen Klassen, dass sie die Klasse \lstinline
    $type$ in ihrer Vererbungshierarchie haben. Die normale Syntax zur
    Definition einer Klasse erzeugt immer eine Instanz von \lstinline
    $type$.
    
    Besonders bemerkenswert sind die Beziehungen zwischen \lstinline
    $type$ und \lstinline $object$, der Wurzel der Vererbungshierarchie
    in Python. Da \lstinline $object$ ein Typ ist, ist es eine Instanz
    von \lstinline $type$. Als New-Style Class muss \lstinline $type$
    gleichzeitig von \lstinline $object$ erben. Zudem ist \lstinline
    $type$ als Metaklasse eine Instanz \emph {von sich selbst}!
    Abbildung~\vref {fig:types} veranschaulicht diese Beziehungen.
    Durchgezogene Linien bezeichnen Vererbungsbeziehungen, gestrichelte
    Linien bezeichnen Instanzierung.

    \subsubsection* {Ein Beispiel}

      Metaklassen können mit wenig Aufwand selbst programmiert und
      benutzt werden. Betrachten wir als Beispiel Listing~\ref
      {lst:metaprog1}.\footnote {Beispiel entnommen aus \cite[Metaclass
      examples]{unify}} Hier wird eine Klasse \lstinline $autoprop$
      definiert, die von \lstinline $type$ erbt und damit eine
      Metaklasse ist. Zweck dieser Klasse ist es, neue Klassen zu
      erzeugen, die automatisch Properties (s.  Abschnitt~\vref
      {properties}) aus Methoden mit einem Namen der Form \lstinline
      $_get_<attribut>$ bzw.  \lstinline $_set_<attribut>$ generieren.

      \lstinputlisting[float=tb,caption=Eine eigene Metaklasse,
        label=lst:metaprog1]{lst/metaprog1.py}

      In dieser Klasse wird nur eine einzige Methode definiert:
      \lstinline $__init__$. Diese Methode wird bei der Instanzierung
      jedes Objekts aufgerufen und wird meist dazu benutzt,
      Objektattribute auf sinnvolle Initialwerte zu setzen. In diesem
      Fall wird die \lstinline $__init__$-Methode genau dann ausgeführt,
      wenn der Interpreter auf eine Klassendefinition trifft, die
      \lstinline $autoprop$ als Metaklasse angibt. Die Parameter dieser
      Methode sind die gleichen, wie die Parameter der \lstinline
      $__init__$-Methode der Oberklasse \lstinline $type$:

      \begin {itemize}
        \item \lstinline $cls$ ist die gerade erzeugte Instanz der aktuell
          definierten Metaklasse,\footnote {\lstinline $cls$ entspricht
          hier \lstinline $self$ in gewöhnlichen Klassen, siehe
          Abschnitt~\vref {self}.}
        \item \lstinline $name$ der Name der neu zu generierenden Klasse,
        \item \lstinline $bases$ ist eine Liste der Oberklassen und
        \item \lstinline $dict$ ist ein Dictionary mit allen Attributen,
          die diese Klasse enthalten soll.
      \end {itemize}

      \lstinputlisting[float=tb,caption=Benutzung von Metaklassen,
        label=lst:metaprog2]{lst/metaprog2.py}

      Zunächst wird \lstinline $super$ benutzt, um die \lstinline
      $__init__$-Methode der Oberklasse (in diesem Fall also \lstinline
      $type$) aufzurufen. Danach wird eine leere Liste mit dem Namen
      \lstinline $props$ erzeugt. Die erste Schleife (ab Zeile~\ref
      {metaprog1:for1}) sucht in der neuen Instanz von \lstinline
      $autoprop$ nach Attributnamen, die dem oben genannten Muster
      entsprechen.  Diese Namen werden abzüglich ihres festen Präfix an
      die Liste \lstinline $props$ angehängt (also bspw. nur noch
      \lstinline $<attribut>$ statt \lstinline $_get_<attribut>)$.

      Für jeden dieser Namen wird in der zweiten Schleife (ab Zeile~\ref
      {metaprog1:for2}) versucht, in der neuen Instanz der Metaklasse ein
      entsprechendes \lstinline $_get_$- bzw. \lstinline $_set_$-Attribut
      zu finden.  Gelingt dies nicht, gibt der Aufruf von \lstinline
      $getattr$ \lstinline $None$ zurück.  Schließlich wird in der neuen
      Klasse mittels \lstinline $setattr$ ein Attribut gesetzt, das von
      der Methode \lstinline $property$ erzeugt wird. Falls eine der
      Variablen \lstinline $fget$ und \lstinline $fset$ \lstinline $None$
      ist, ist das entsprechende Objektattribut nur schreib- bzw. lesbar.

      In Listing~\vref {lst:metaprog2} sieht man eine mögliche Anwendung
      der Metaklasse \lstinline $autoprop$.\footnote {Beispiel angelehnt
      an \cite[Metaclass examples]{unify}.} Die Klasse \lstinline $AbsX$
      soll einen Integerwert speichern können (genauer gesagt jedes
      Objekt, das die Methode \lstinline $__abs__$ implementiert).
      \emph {Der Betrag} dieses Wertes soll als Objektattribut \lstinline
      $x$ erreichbar sein, während gleichzeitig der tatsächlich gesetzte
      Wert gespeichert wird. Eine elegante Möglichkeit dies zu
      erreichen, ist die Benutzung von Properties, wie sie von
      \lstinline $autoprop$ bereitgestellt werden. \lstinline $AbsX$
      definiert also \lstinline $_get_x$ und \lstinline $_set_x$ als
      Getter und Setter für das zu erzeugende Attribut \lstinline $x$
      und deklariert in Zeile~\ref {metaprog2:meta} \lstinline
      $autoprop$ als ihre Metaklasse. Damit ist ein Zugriff auf das
      Attribut \lstinline $x$ möglich, obwohl weder ein solches Attribut
      gesetzt, noch die Funktion \lstinline $property$ explizit benutzt
      wurde.  Wird nun diesem Attribut eine negative Zahl zugewiesen,
      bekommen wir beim Auslesen dieses Wertes dessen Betrag
      zurückgeliefert.
