Seite 1 von 2
Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 12:32
von api
Hallo zusammen,
ich habe mal eine Verständnisfrage zum Kopieren von Strings.
Wenn ich einen String kopiere möchte, so dachte ich, dass ich dieses per Slicing erledigen kann:
>>> a = "Text"
>>> b = a[:]
>>> a
'Text'
>>> b
'Text'
>>> id(a)
319552
>>> id(b)
319552
Nun erhalte ich aber die gleiche ID. Ist das nun eine Kopie oder nicht? Es scheint, als ob es wohl nur eine Quasi-Kopie mit einer Referenz ist.
Wenn ich das per Zuweisung mache, kommt das gleiche raus:
>>> a = "Text"
>>> b = a
>>> a
'Text'
>>> b
'Text'
>>> id(a)
319552
>>> id(b)
319552
Frage: Wie lege ich denn nun eine wirkliche Kopie an? Also, mit einer neuen ID?
CU,
API
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 12:36
von webspider
Da Slicing flache Kopien erstellt, suchst du wohl nach
tiefen.
Dennoch würde ich nicht übermäßigen Gebrauch davon machen und mich lieber mit den Eigenheiten der Programmiersprache anfreunden.
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 12:40
von api
Das soll jetzt was heissen?
Ist es eine Eigenart von Python keine Kopien (tief) von Strings anzulegen? Oder was meinst du damit?
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 12:52
von Hyperion
Strings sind in Python *immutuable*; d.h. Du kannst sie nicht ändern. Jede String-Methode erzeugt also einen neuen String im Speicher. Nun überlege mal, wofür man also eine 1:1 Kopie eines Strings gebrauchen könnte?
@webspider: `copy` nützt Dir hier auch nichts:
Code: Alles auswählen
In [55]: import copy
In [56]: s = "Hallo Welt"
In [57]: s_copy = copy.copy(s)
In [58]: s is s_copy
Out[58]: True
In [59]: s_copy = copy.deepcopy(s)
In [60]: s is s_copy
Out[60]: True
Ist doch eigentlich nett, dass Python hier "optimiert"

Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 12:56
von snafu
Ich frage mal anders: Wieso willst du von einem String eine Kopie anlegen? Zeichenketten sind in Python unveränderlich. Für welchen Einsatzzweck soll das also gut sein?
Die Frage nach der selben ID kann ich nicht beantworten, gehe aber stark davon aus, dass sie etwas mit der besagten Unveränderlichkeit zu tun hat.
Hier gibt's aber sicher jemanden, der das weiß. Einfach mal abwarten...

Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 13:09
von api
Ja danke schonmal - das war sehr hilfreich.
Also, liegt das wohl daran, dass Strings "immutable" sind...
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 13:27
von webspider
Hyperion hat geschrieben:Ist doch eigentlich nett, dass Python hier "optimiert"

Ja und wie
Wie gesagt, mir hat diese Eigenart nur anfangs Probleme gemacht, erst mit Strings ("Es wäre doch besser wenn es nur einen Buchstaben verändert statt gleich einen neuen String zu erstellen!"), dann mit Listen. Sobald man lernt "pythonischer" zu denken, die alten Gewohnheiten hinter sich lässt und versteht wie intern optimiert wird, lernt man IMO Python erst richtig zu schätzen.
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 13:39
von Hyperion
Numbers sind übrigens auch immutable - einen Integerwert kann man auch nicht "kopieren"

Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 13:41
von api
Nun ja, ich habe ja gar nicht gesagt, dass ich eine neue ID will - ich wollte es nur verstehen, warum Python sich so verhält
Da Python hier wohl eigenständig Optimierung betreibt ist schon gut - man muss es halt nur wissen...

Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 13:51
von Hyperion
api hat geschrieben:
Da Python hier wohl eigenständig Optimierung betreibt ist schon gut - man muss es halt nur wissen...

Hm... wo trifft Dich das denn in der Praxis? Die Anfängerfragen in diesem Forum mal als repräsentative Basis genommen, taucht diese Frage sehr selten auf - der andere Fall, nämlich das Kopieren von veränderbaren Objekten macht da viel mehr Probleme... und da Anfänger das alles meist eh nicht wissen, scheint das (Nicht-)Wissen über diesen Fall wohl keine große Relevanz zu haben

Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 14:38
von jerch
CPython gibt im [:] Falle einen Pointer auf den zu slicenden String zurück:
Code: Alles auswählen
if (i == 0 && j == Py_SIZE(a) && PyString_CheckExact(a)) {
/* It's the same as a */
Py_INCREF(a);
return (PyObject *)a;
}
Daher die Objektidentität.
Urgh, die '&'s oben sind eigentlich '&', kA wie man das dem Codehighlighter beibringt.
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 15:02
von snafu
In dem Zusammenhang übrigens auch ganz "interessant":
Code: Alles auswählen
>>> 'foo' is 'foo'
True
>>> 'foo' is ''.join('foo')
False
Wobei natürlich:
Auch ein Folgeaufruf von `id(''.join('foo'))` führt zu jeweils unterschiedlichen Ergebnissen, während ein simples `id('foo')` immer dieselbe ID zurückgibt.
Das ist zwar alles sehr strange und bestimmt auch kein garantiertes Verhalten, aber zumindest hätte man somit offenbar eine "echte" Kopie des Strings. Wie gesagt: Von der Verwendung in diesem Zusammenhang würde ich jedoch lieber abraten.
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 15:14
von api
Sicherlich ist das mit der eigenen ID - bei einer Kopie - nichts, was man im täglichen Leben benötigt. Aber ich habe das mit der ID nunmal ausprobiert und mich anschließend gefragt, warum da immer die gleiche ID rauskommt.
Ich war eigentlich davon ausgegangen, dass es dann zwei unterschiedliche IDs gibt.
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 15:20
von snafu
Hui, man kann das Verhalten von `str.join()` nichtmal so begründen, dass zusammengesetzte Strings etwas anderes sind als "normale" Strings, denn:
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 15:23
von BlackJack
Noch etwas zum Nachdenken über IDs:
Vielleicht ist es sofort klar was hier passiert, vielleicht muss der ein oder andere ein wenig darüber nachdenken.

Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 15:26
von snafu
Hab hier noch sowas:
Code: Alles auswählen
>>> result = ""
>>> for char in "foo":
... result += char
...
>>> result is "foo"
False
>>> result
'foo'
>>> result = "foo" # Neuzuweisung
>>> result is "foo"
True
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 15:31
von jerch
Und weiter gehts:
Code: Alles auswählen
>>> a='abc'
>>> b='abc'
>>> a is b
True
>>> a='a bc'
>>> b='a bc'
>>> a is b
False
>>> a='abc'
>>> b='abc'
>>> a is b
True
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 15:36
von snafu
Gibt es da ein bestimmtes System hinter oder sollte man mit dem Vergleich auf Objektidentität wirklich sehr sehr vorsichtig umgehen? Es ist ja ohnehin klar, dass Vergleiche vornehmlich über den Wert gemacht werden sollten und nicht über die Identität, weil's halt etwas ganz anderes ist, was manchmal nur zufällig übereinstimmt.
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 16:08
von api
@snafu: Also bei ergibt das folgende Konstrukt aber ein "False"...
>>> "foo" is "f" + "o" + "o"
False
Re: Slicing & Copy
Verfasst: Mittwoch 18. Januar 2012, 16:44
von api
@snafu: Ich muss mich korrigieren. Es gibt Unterschiede zwischen Python 2.x und 3.x (ok, natürlich, aber ich meine diesen speziellen Fall jetzt...)
Python 2:
>>> "foo" is "f" + "o" + "o"
False
Python 3:
>>> "foo" is "f" + "o" + "o"
True
Es sieht so aus, als ob Python3 noch etwas mehr optimiert...
