Seite 1 von 1

funktion: liste tief kopieren (rekursiv)

Verfasst: Samstag 17. Januar 2009, 18:55
von PinkPython
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.

Verfasst: Samstag 17. Januar 2009, 19:04
von BlackVivi

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])

Verfasst: Samstag 17. Januar 2009, 19:07
von PinkPython
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 :(.

Verfasst: Samstag 17. Januar 2009, 19:49
von DatenMetzgerX

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

Verfasst: Samstag 17. Januar 2009, 22:21
von PinkPython
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?

Verfasst: Samstag 17. Januar 2009, 22:49
von Birne94
es ist besser, weil man dann imo auch abgeleitete Klassen erfasst, odder??

Verfasst: Samstag 17. Januar 2009, 22:56
von cofi

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 ;)

Verfasst: Sonntag 18. Januar 2009, 10:44
von HWK
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

Verfasst: Sonntag 18. Januar 2009, 11:03
von Darii
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.

Verfasst: Sonntag 18. Januar 2009, 13:10
von numerix
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.

Verfasst: Sonntag 18. Januar 2009, 14:02
von PinkPython
Dankeschööööön, jetzt habe ich es verstanden. Das Forum ist einfach super ;-). Danke an alle.