funktion: liste tief kopieren (rekursiv)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
PinkPython
User
Beiträge: 4
Registriert: Samstag 17. Januar 2009, 18:40

Hallo,

ich bin Python-Anfänger und wollte daher fragen, ob jemand weiß wie ich am besten eine Liste tief kopieren kann, und wie ich eine möglichst einfache Funktion dazu schreiben kann.

Z.B: Möchte ich:

liste1=[1,2,3,[4,5],6,7]
neueliste= listdeepcopy(liste1)

So, dass auch die verschachtelten listen mitkopiert werden. Die Funktion deepcopy ist daher genau das was das macht, nur ich möchte es nur für listen, und als "eigene" Funktion haben und zwar rekursiv.


Ich habe es so probiert:

Code: Alles auswählen

def listdeepcopy(l):
    k=[]
    for e in l:
        if isinstance( e, list ):
            k.append(listdeepcopy(e))
        else:
            k.append(e)
    return k

Aber mir scheint die Methode trotzdem falsch zu sein :(, da bei k.append(listdeepcopy(e)), man es auch weglassen kann, und somit kein Sinn ergibt. :(
Weiß jemand wie ich das besser machen kann?
Vielen Dank im vorraus.
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Code: Alles auswählen

>>> import copy
>>> copy.deepcopy
<function deepcopy at 0x00AC68B0>
>>> foo = [1,2,3]
>>> bar = foo
>>> foobar = copy.deepcopy(foo)
>>> foo.append(4)
>>> foo, bar, foobar
([1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3])
>>> foobarbar = foo[:]
>>> foo.append(5)
>>> foo, bar, foobar, foobarbar
([1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3], [1, 2, 3, 4])
PinkPython
User
Beiträge: 4
Registriert: Samstag 17. Januar 2009, 18:40

Danke BlackVivi, aber ich darf hierbei keine python funktione wie copy.deepcopy verwenden, sondern wirklich "eigene" schreiben. Meine Funktion sollte schon ein Methoden-Kopf haben, und eine neue Liste zurückgeben. Ich komme leider bei meiner Funktion nicht sonderlich weiter :(.
Benutzeravatar
DatenMetzgerX
User
Beiträge: 398
Registriert: Freitag 28. April 2006, 06:28
Wohnort: Zürich Seebach (CH)

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: utf-8 -*-

def copy(iter):
    result = list()
    for item in iter:
        if isinstance(item, list):
            result.append(copy(item))
        else:
            result.append(item)
            
    return result


if __name__ == '__main__':
    l = ["abe", 2, 3, 4, 5, [23, 45]]
    c = copy(l)
    
    l.append(10)
    c.append(34)
    c[0] = c[0] + "t"
    c[5].append(90) 
    
    print l
    print c
Funktioniert bei mir bestens, Python 2.5.2
PinkPython
User
Beiträge: 4
Registriert: Samstag 17. Januar 2009, 18:40

stimmt, ich war nur etwas irritiert, wegen der Zeile 8. Wenn man da im append, den rekursiven Aufruf weglässt, ändert sich nichts.
Danke!

Noch eine kleine Frage, kann ich statt ininstanceof, auch:

Code: Alles auswählen

if type(e)==list:
schreiben? Im Prinzip hätte es den selben Effekt, aber ist es besser type oder isinstanceof zu verwenden?
Birne94
User
Beiträge: 90
Registriert: Freitag 28. November 2008, 15:18
Kontaktdaten:

es ist besser, weil man dann imo auch abgeleitete Klassen erfasst, odder??
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Code: Alles auswählen

In [1]: class AnotherList(list):
   ...:     pass
   ...:

In [2]: alist = AnotherList()

In [3]: isinstance(alist, list)
Out[3]: True
Man sollte aber vielleicht jedes iterable - ausser Strings - einschliessen, um wirklich ein deepcopy zu schaffen ... aber existiert ja schon ;)
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

PinkPython hat geschrieben:Danke BlackVivi, aber ich darf hierbei keine python funktione wie copy.deepcopy verwenden, sondern wirklich "eigene" schreiben. Meine Funktion sollte schon ein Methoden-Kopf haben, und eine neue Liste zurückgeben. Ich komme leider bei meiner Funktion nicht sonderlich weiter :(.
Du kannst Dir aber ja trotzdem mal die Implementierung der Methode deepcopy in Python26/Lib/copy.py anschauen.
MfG
HWK
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

PinkPython hat geschrieben:stimmt, ich war nur etwas irritiert, wegen der Zeile 8. Wenn man da im append, den rekursiven Aufruf weglässt, ändert sich nichts.
Danke!
Nein kann man nicht. Probier mal

Code: Alles auswählen

liste1 = [1,2,3,[4,5],6,7] 
liste2 = liste1[3]
liste3 = listdeepcopy(liste1)
liste2[1] = 23
print liste3
mit und ohne rekursiven Aufruf.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

PinkPython hat geschrieben:Noch eine kleine Frage, kann ich statt ininstanceof, auch:

Code: Alles auswählen

if type(e)==list:
schreiben? Im Prinzip hätte es den selben Effekt, aber ist es besser type oder isinstanceof zu verwenden?
Die library reference sagt (http://docs.python.org/library/functions.html)
type(object)¶
Return the type of an object. The return value is a type object. The isinstance() built-in function is recommended for testing the type of an object.
PinkPython
User
Beiträge: 4
Registriert: Samstag 17. Januar 2009, 18:40

Dankeschööööön, jetzt habe ich es verstanden. Das Forum ist einfach super ;-). Danke an alle.
Antworten