[Python-de] Parameter in Python

Clemens Hintze cle at qiao.in-berlin.de
Di Nov 12 08:02:42 CET 2013



Alexander Langer schrieb:
> Moin,

Guten Morgen,

> ich hatte ein interessante und zugleich verwirrende Diskussion über
> Funktionsparameter im IRC Chat #python.

Ich glaube, dass es sich hier *nicht* um mutable/immutable dreht. Der
Mechanismus, wie *Variablen* in ein Unterprogramm übergeben werden, hat
nichts mit Immutabilität zu tun, IMO. Es mag zwar den Anschein erwecken,
ist aber eine dazu orthogonale Eigenschaft.

> Das Problem dreht sich um mutable / immutable Werte.
> 
> Beispiel Zahl als Funktionsparameter -> Veränderung nur lokal sichtbar.
> Beispiel Liste als Funktionsparameter -> Veränderung global sichtbar.

Eine Zahl ist immer unveränderlich, da sie atomar ist. Es ist noch
niemanden gelungen, aus einer 12 eine 13 zu machen. Eine Zahl ist also
*immer* immutable.

Eine Liste hingegen kann veränderbar sein, oder eben nicht. Das hat
jetzt aber nichts damit zu tun, wie sie als Parameter übergeben wird.

> Auf meine Frage, ob letzteres nicht call-by-reference (cbr) sei,
> erwiderte man das sei alles, wirklich alles call-by-value (cbv) weil man
> da ja Zeiger auf Objekte als Werte übergebe.

Das ist korrekt! Die Begriffe Call-by-Referece und Call-by-Value
beziehen sich eher auf die Variablen, die man dem Unterprogramm übergibt.

> Für mich ist das eine befremdliche Auffassung (und vielleicht auch
> Taktik um von einem Manko abzulenken), denn hinter cbr und cbv steht in
> erster Linie eine Semantik für den Programmierer und nicht die Frage wie
> ich die Parameter implementiere. So jedenfalls habe ich es damals gelernt.

Wenn du eine Variable Call-by-Reference runterreichst, erlaubst du der
Funktion, den _Inhalt_ der Variablen im Aufrufenden zu ändern (zum
Beispiel: zu überschreiben). Du könntest also auch eine völlig andere
neue Liste in die Variable stopfen. In folgendem Pascal-Beispiel:

   procedure swap(var a, b : integer)
   var t : integer;
   begin
     t :=;
     a :=;
     b :=;
   end;

   v1 :=2;
   v2 :=;

   swap(v1, v2);

werden tatsächlich die Inhalte von v1 und v2 geändert/ausgetauscht. Wenn
die Funktion (hier eine Prozedur) also auf 'a' arbeitet, arbeitet sie in
Wirklichkeit mit der Variablen 'v1'.

Wie dieser Mechanismus realisiert ist, ist Sache des Compilers. Als
Programmierer musst du nur wissen, dass deine Variablen geändert werden
können.

Davon zu unterscheiden ist, wie ein Objekt in einer Variablen gehalten
wird. Ob per Referenz auf das Objekt, oder als Wert.

Achtung: Eine Variable mag eine Referenz auf eine Liste halten. Das ist
aber unabhängig davon, wie diese Variable nach "unten" übergeben wird.
Also ob der Wert (die Referenz auf die Liste), oder eine Referenz auf
die wert-haltende Variable runtergereicht wird.

> Mich würde mal interessieren, warum dieses Problem nicht schon längst
> angegangen wurde und ob ihr schon damit Kontakt hattet. Ich jedenfalls
> muss meine mutables allehand kopieren, um unerwünschte Seiteneffekte zu
> vermeiden.

Hmmm ... ich denke, das "Problem" wurde nicht angegangen, da es keines
ist! Es handelt sich hier um zwei völlig verschiedene Konzepte, wie ich
oben dargelegt habe. Diese zwei Konzepte ergänzen sich, beeinflussen
sich aber nicht!

Oftmals spielen auch einfachere Implementierung des Compilers, oder
Performance-Überlegungen eine Rolle bei der Frage, ob komplexere Objekte
nun als Werte oder Referenzen in einer Variablen gehalten werden.

Wenn du es mit großen Listen zu tun hast, und diese jedes Mal kopieren
musst, wenn du sie einem Unterprogramm übergibst, wirst du schnell auf
einen üblen Engpass stoßen nach mehr Performance rufen!

In Python hat man sich nunmal dafür entschieden, Listen als Referenzen
in Variablen zu halten.


Grüße,
cle.



Mehr Informationen über die Mailingliste python-de