Seite 1 von 1

objekte direkte manipulation oder return

Verfasst: Dienstag 24. Februar 2009, 10:27
von joliebig
Hi,
meine Frage dreht sich um eine allgemeingueltige Regel fuer das Verhalten von Objekten und deren zugehoerigen Methoden. In einigen Faellen werden Python-Objekte direkt durch Methoden manipuliert. So wuerde ich es auch erwarten. Ein Beispiel:

Code: Alles auswählen

a = [1, 2, 3]
a.append(4)
print(a)
Nutzt man hingegen die __add__ Funktion sieht es anders aus.

Code: Alles auswählen

a.__add__([5])
>> [1, 2, 3, 4, 5]
print(a)
[1, 2, 3, 4]
Aehnliches findet sich auch an anderen Stellen (bspw. Stringverarbeitung). Gibt es allgemeingueltige Regeln zum Verhalten von Objekten und deren Methoden zur Manipulation oder muss man das Verhalten kennen. Ich frage aus dem Grund, weil dieser Unterschied schon haeufig eine Fehlerquelle in meinen Programmen war.

Fuer Eure Muehe im voraus besten Dank
joliebig

Verfasst: Dienstag 24. Februar 2009, 10:43
von b.esser-wisser
Gibt es eine Regel dafür?
Klares Ja
Wenn das Objekt verändert wird, gibt die Methode None zurück.

Ob ein Objekt verändert wird (oder werden kann) steht (hoffentlich) in der Doku (z.B. unicode/int/complex/tuple etc. sind "immutable", die kann man nicht verändern).


Und man kann oft aus dem Namen schließen, ob was verändert wird (append=>"anhängen", aber sorted=>"sortiert" nicht "sortier!").

Dein Beispiel mit "__add__" ist etwas irreführend, weil man "__add__" nie direkt benutzt, man nimmt "+":

Code: Alles auswählen

Python 2.5.1 Stackless 3.1b3 060516 #...
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [1,2,3]
>>> a + [4,5]
[1, 2, 3, 4, 5]
>>> a
[1, 2, 3]
>>> a + 4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "int") to list
Wenn sich da "a" verändern würde, wäre das etwas unerwartet(evtl. suchst du ja "+=" also "__iadd__").

hth, Jörg
edit: typos, überall typos

Verfasst: Dienstag 24. Februar 2009, 10:48
von Darii
Das Verhalten ergibt sich sich daraus, was du machst. Mit append hängst du an eine vorhandene Liste ein Element an (dadurch bleibt die Liste natürlich gleich). Mit __add__ (was einfach dem "+"-Operator entspricht) fügst du zwei Listen zu einer neuen zusammen. Wenn du einfach nur eine andere Liste an die Liste anhängen willst, muss du list.extend benutzen.

Die Antwort auf deine Frage lautet also: Man muss das Verhalten kennen, meist wird das aber Objekt verändert. Bei Strings wird sowieso immer ein neues Objekt erstellt, da Strings unveränderlich sind.

Verfasst: Dienstag 24. Februar 2009, 10:51
von helduel
Moin,

da hilft meist nur Doku lesen.

Zu deinem Beispiel:
append ist eine Methode und arbeitet auf der Instanz - fügt der Instanz also ein Element hinzu.

__add__ ist eine spezielle Methode, die automatisch aufgerufen wird, wenn du den +-Operator benutzt:

Code: Alles auswählen

l1 = [1, 2, 3]
l2 = [4, 5, 6]
l3 = l1 + l2
Hier wird eine dritte Liste erzeugt, mit den Elementen aus beiden Listen. Warum sollte hier die erste Liste geändert werden? Wenn du Listen zu einer Liste hinzufügen willst, dann gibt es die Methode extend (also wieder Doku lesen).

Gruß,
Manuel

Verfasst: Mittwoch 25. Februar 2009, 04:34
von str1442
Immutable Objekte geben immer ein neues Objekt zurück, __underscore__ Methoden, welche einen Operator implementieren, geben immer ein neues Objekt zurück mit Ausnahme der "augmented" Operatoren. Das sind alle Operatoren mit einem "=": Für __add__ wäre das __iadd__ und entspricht +=, was das bei einer Liste das gleiche wie extend macht. Diese Methoden haben immer so ein vorangestellstes "i". Ist ein Objekt Mutable (veränderlich) und besitzt normale Methoden, die keinerlei speziellen Wert zurückgeben müssen (ala list.count, welches ja einen Integer zurück gibt), werden sie direkt auf das Objekt angewandt. Das ist die Regel. Man kann natürlich nicht generell davon ausgehen, da im Endeffekt der Programmierer die Macht hat, aber jede halbwegs gute Klasse sollte so agieren.

Verfasst: Mittwoch 25. Februar 2009, 10:24
von joliebig
Vielen Dank - Eure Antworten haben mir sehr geholfen Python wieder etwas besser zu verstehen.