Funktion verändert input-argument, ohne dass sie es soll

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.
Elemenope
User
Beiträge: 8
Registriert: Donnerstag 25. Januar 2018, 18:09

Hallo,

ich wollte eine sehr einfache Verkehrssimulation nach dem Nagel-Schreckenberg-Modell schreiben. Die Funktioniert so weit auch gut, alle Fahrzeuge bewegen sich so wie gewollt.
Nur wird dabei jedes mal die "Straße", die ich als Input gebe, verändert:
a
Out[3]: [4, 5, -1, 5, -1, -1, -1, 2, 0, -1, -1, -1, 4, -1, 0]

NaSch(a,0,5)
Out[4]: [0, -1, 1, -1, -1, -1, 3, 0, -1, 1, -1, -1, -1, 1, -1]

a
Out[5]: [0, 1, -1, 3, -1, -1, -1, 0, 1, -1, -1, -1, 1, -1, -1]

Das verstehe ich nicht, da ich die input-Liste nur am Anfang einmal kopiere und ansonsten nicht anrühre. Hier der Code der Funktion:

Code: Alles auswählen

def NaSch(st,p,v,a=1):
    """
    Umsetzung Nagel-Schreckenberg, s: Straße,
    p: Trödel.wsk. v: max Geschwind., a: Beschleunigung
    """
    s = st
    # 1. Schritt: Beschleunigung für Fahrzeuge unter max. v + Trödel.wsk.
    for i in range(0,len(s)):
        if s[i] != -1:
            if s[i] < 5:
                s[i] += a
            if s[i] > 0:
                if random.randint(1,100) < p:
                    s[i] -= 1
    
    # 2. Schritt: Begrenzung der Geschwindigkeit durch andere Fahrzeuge
    for i in range(0,len(s)):
        if s[i] != -1:
            for j in range(i+1,i+s[i]+1):
                try:
                    if s[j] != -1:
                        s[i] = j-i-1
                        break
                except IndexError:
                    s[i] = -1
    
    # 3. Schritt: Ausführen der Bewegungen
    s_n = [-1]*len(s)
    for i in range(0,len(s)):
        if s[i] != -1:
            s_n[i+s[i]] = s[i]
    
    return s_n
Es wäre super, wenn mir jemand bei des Rätsels Lösung helfen könnte. Für mich ergibt das erstmal überhaupt keinen Sinn.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kopierst nicht.

x = y

macht in Python keine Kopie. Es heftet dem gleichen Objekt nur ein neues Namensschild an die Brust. Ist aber immer noch die gleiche Liste. Du musst schon wirklich kopieren. In deinem Fall reicht einfach ein list(st), an anderen Stellen muss ggf. ein deepcopy gemacht werden, wenn die Liste ihrerseits wieder veraenderbare Objekte wie Listen oder Woerterbuecher enthaelt.

Code: Alles auswählen

>>> a = []
>>> b = a
>>> id(a)
140188226488200
>>> id(b)
140188226488200
>>> b = list(a)
>>> id(a)
140188226488200
>>> id(b)
140188226498952
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Elemenope: Ich denke mal Du hast eine falsche Vorstellung davon was die erste Zeile macht. Du gibst der Liste die unter dem Namen `st` bekannt war einfach nur den zusätzlichen Namen `s`. Python kopiert bei Zuweisungen an Namen und Funktionsaufrufen nie von sich aus Werte. Du wollest da vielleicht ``s = list(st)`` schreiben um eine (flache) Kopie zu bekommen.

Du benutzt ein bisschen viel vom ``for i in range(len(sequence)):``-„anti pattern“. Man kann in Python *direkt* über die Elemente von Sequenzen iterieren, ohne den Umweg über einen Index. Falls man den *zusätzlich* benötigt, gibt es die `enumerate()`-Funktion.

Die Namensgebung ist übrigens besch…eiden. Namen sollen dem Leser vermitteln was die Werte bedeuten, nicht zum rätselraten oder nach Doku oder Kommentar mit einer Auflösung von Kürzeln suchen zu lassen. Zudem schreibt man in Python alles ausser Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase) in klein_mit_unterstrichen.

Edit: In der ersten Schleife könntest Du schon die explizite Kopie vorher unnötig machen in dem Du nicht die vorhandene Liste änderst, sondern einfach eine neue aufbaust. Damit sind dann auch die Indexzugriffe in der Schleife geschichte.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Elemenope
User
Beiträge: 8
Registriert: Donnerstag 25. Januar 2018, 18:09

@deets und blackjack:
Danke für die schnellen Antworten, damit ist mein Problem ja gelöst.

und bezüglich der Variablennamen: ich stehe, wie man merkt, noch ziemlich am Anfang und bringe mir das ein wenig selbst bei. Darum habe ich da noch kein wirkliches System. Aber danke für die freundliche Anmerkung ;>

Bezüglich der for-loops werde ich mich mal damit beschäftigen, was genau gemeint ist
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Elemenope: Die übergebene Maximalgeschwindigkeit wird in der Funktion gar nicht verwendet, da steht eine hart kodierte 5 *und* die Funktion begrenzt die Geschwindigkeit(en) gar nicht auf diese 5 wenn man für `a` andere Werte als 1 verwendet.

-1 für Leere Felder ist auch keine gute Idee weil das ja eine normale Zahl ist, die bei Fehlern im Algorithmus einfach verrechnet wird, ohne dass das auffällt. Da wäre es sinnvoller zum Beispiel `None` für leere Felder zu verwenden – wenn man damit aus versehen versucht zu rechnen, dann führt das zu einer Ausnahme statt stillschweigend einen falschen Wert zu produzieren.

Die Begrenzung der Geschwindigkeit wegen anderer Fahrzeuge ist wenn ich das richtig sehe falsch. Oder Nagel-Schreckenberg definiert das so falsch/unrealistisch.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Statt Listen zu kopieren und/oder zu verändern, ist es in Python üblich, einfach eine neue Liste zu erzeugen.
Aus Schritt 1 wird also:

Code: Alles auswählen

def beschleunigen(geschwindigkeit, troedel_wahrscheinlichkeit, maximal_geschwindigkeit, beschleunigung):
    if geschwindigkeit != -1: # besser `is not None`
        if geschwindigkeit < maximal_geschwindigkeit:
            geschwindigkeit += beschleunigung
        if geschwindigkeit > 0:
            geschwindigkeit -= random.randint(1,100) < troedel_wahrscheinlichkeit
    return geschwindigkeit

def nagel_schreckenberg(strasse, troedel_wahrscheinlichkeit, maximal_geschwindigkeit,beschleunigung=1):
    # 1. Schritt: Beschleunigung für Fahrzeuge unter max. v + Trödel.wsk.
    strasse = [beschleunigen(g, troedel_wahrscheinlichkeit, maximal_geschwindigkeit, beschleunigung)
        for g in strasse]
    # 2. Schritt: Begrenzung der Geschwindigkeit durch andere Fahrzeuge
    ...
Elemenope
User
Beiträge: 8
Registriert: Donnerstag 25. Januar 2018, 18:09

@blackjack
Das mit der max. Geschwindigkeit stimmt. Danke, für den Hinweis.

Das mit None werde ich mir überlegen. Ist ja leicht gemacht und mir fallen erstmal keine Folgeprobleme ein

Das hier ist natürlich erstmal eine ganz grundlegende Implementierung des Modells. Ich habe auch vor später die Geschwindigkeit der vorausfahrenden Fahrzeuge antizipieren zu lassen. Daneben sind noch eine Vielzahl weiterer Elemente denkbar, um das Modell realistischer zu machen. z.B. Mehrspurigkeit, Unfälle, Wetterbedingungen, ...
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Elemenope: Ist das mit der Wahrscheinlichkeit korrekt? Ich hätte da ja einen Zufallswert von 0 bis 100 und nicht 1 bis 100 erwartet.Beziehunsgweise bei einem Argument `p` für die Wahrscheinlichkeit einen Wert zwischen 0 und 1 und nicht 0 und 100. Wenn das in Prozent angegeben werden muss/soll, würde ich das explizit dokumentieren.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Elemenope
User
Beiträge: 8
Registriert: Donnerstag 25. Januar 2018, 18:09

@blackjack:
0 wäre richtig. Dass die Wahrscheinlichkeit in % angegeben werden soll, steht weiter oben in der Funktion, mit der ich mir zufällige Straßen erstellen lasse. Hab es für NaSch nicht nochmal aufgeschrieben. Dazu muss ich sagen, dass das hier wirklich nur ein kleines Projekt von mir ist, das eigentlich nicht veröffentlich werden soll.
Einen besseren Dokumentations/Bennenungsstil sollte ich mir vielleicht trotzdem angewöhnen. Wurde ja jetzt schon von verschiedenen Seiten angemerkt.

Mal eine andere Frage: Kann mir jemand eine gute Library/Programmnennen. Mit der ich die Daten später mal schön visualisieren kann? Mir schwebt vor irgendwann ein mal Straßennetzwerk darzustellen und animiert zu zeigen wie sich die Verkehrsdichte so über die Zeit entwickelt. Genauere Gedanken habe ich mir noch nicht gemacht - ist auch noch Zukunftsmusik. Ansonsten wäre es auch schon mal praktisch das irgendwie für eine einzelne Straße darstellen zu können. Ob als Animation oder nicht ist erstmal egal.
Ich erwarte hier auch eine großen Erklärungen. Möchte mich da selbst reinfuchsen. Aber ein geeignetes Werkzeug zu kennen wäre hilfreich.
Danke im Voraus.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Habe mich auch mal an dem Modell versucht und mich gegen eine Liste entschieden wo jeder Eintrag für einen eine Autolänge langen Abschnitt auf der Strasse entspricht, weil ich die nötige Schleife für die Abstandsmessung zum vorfahrenden Auto nicht so prickelnd finde. Wenn man pro Auto Position und Geschwindigkeit speichert, kann man die neue Position für den nächsten Schritt in konstanter Zeit berechnen, unabhängig von Strassenlänge und Autodichte. Der Code sieht dann auch mehr nach Python aus, das heisst keine Indexlaufvariablen. :-)

Code: Alles auswählen

#!/usr/bin/env python3
import random

from attr import attrib, attrs
from more_itertools import pairwise, prepend


@attrs
class Car:
    position = attrib()
    velocity = attrib(default=0)
    
    def distance(self, other):
        return other.position - self.position


@attrs
class Street:
    length = attrib()
    deceleration_probability = attrib()
    cars = attrib()
    max_velocity = attrib(default=5)
    acceleration = attrib(default=1)

    def __iter__(self):
        return iter(self.cars)
    
    def distance(self, car_a, car_b):
        result = car_a.distance(car_b)
        if result < 0:
            result += self.length
        return result

    def _update_velocity(self):
        for car_a, car_b in pairwise(prepend(self.cars[-1], self)):
            car_a.velocity = max(
                0,
                min(
                    self.max_velocity,
                    car_a.velocity + self.acceleration,
                    self.distance(car_a, car_b) - 1
                ) - (random.random() < self.deceleration_probability)
            )

    def _update_position(self):
        for car in self:
            car.position = (car.position + car.velocity) % self.length
        
    def update(self):
        self._update_velocity()
        self._update_position()

    def as_row(self):
        row = [0] * self.length
        for car in self:
            row[car.position] = 1
        return row

    @classmethod
    def with_car_density(cls, length, deceleration_probability, car_density):
        positions = random.sample(range(length), int(length * car_density))
        positions.sort()
        cars = [Car(position) for position in positions]
        return cls(length, deceleration_probability, cars)


def main():
    street_length = 320
    step_count = 256
    
    street = Street.with_car_density(street_length, 0.3, 0.35)
    
    print(f'P1\n{street.length} {step_count}\n')
    for _ in range(step_count):
        street.update()
        print(''.join(map(str, street.as_row())))


if __name__ == '__main__':
    main()
Das Programm gibt ein Bild im „portable bitmap“-Format (PBM) auf der Standardausgabe aus. Hier ein Beispiellauf:
Bild
Womit wir bei der Visualisierung wären: Es ist schwierig da etwas zu empfehlen, wenn Du selbst noch gar nicht so genau weisst was Du da gerne machen möchtest. Mit einfachsten Mitteln, also einfach nur `print()` kann man eine Grafik wie in diesem Beitrag erstellen. Python kommt mit `tkinter` in der Standardbibliothek wo man mit `Canvas` sicher etwas machen kann. Es gibt aber auch einige andere Grafikbiblotheken und GUI-Rahmenwerke. Je nach dem was da sonst noch angedacht ist, auf welchem System oder Systemen das laufen soll, und letztlich auch welche Lizenzen (un)erwünscht sind, kann man das Einschränken.

Grundsätzlich sollte die Simulation selbst möglichst unabhängig von einer späteren Darstellung gehalten werden, damit man da mehr oder weniger beliebige grafische Aufsätze drauf setzen kann.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Elemenope
User
Beiträge: 8
Registriert: Donnerstag 25. Januar 2018, 18:09

An Klassen/OOP habe ich mich bisher noch nicht rangewagt. Ist für mich erstmal weniger intuitiv zugänglich als einfach for-Schleifen und if-Bedingungen zusammenzuklatschen. Aber es wird mal Zeit und es ist schön, hier mal ein Code Beispiel zu haben, bei dem ich weiß, was es tun soll.
Die einfache Visualisierung aus dem Beispiel ist ganz nett, man sieht schön, wie sich die kleinen Staus auf der Straße nach hinten bewegen.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Elemenope: Naja, ``for``-Schleifen sind in der OOP-Variante ja auch das Mittel der Wahl und die ``if``\s sind in den Funktionen `min()` und `max()` verschwunden, das heisst das wäre bei einer nicht-OOP-Variante genau so ohne die ``if``\s. Wirklich wichtig ist IMHO die Laufindexvariablen los zu werden, denn das ist nicht „pythonisch“, egal ob nun mit oder ohne Klassen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das ganze mal ohne Klassen, eher funktional gelöst:

Code: Alles auswählen

#!/usr/bin/env python3
import random

from more_itertools import iterate, pairwise, prepend, take


def make_car(position, velocity=0):
    return (position, velocity)


def get_car_distance(car_a, car_b, street_length):
    position_a, _ = car_a
    position_b, _ = car_b
    distance = position_b - position_a
    if distance < 0:
        distance += street_length
    return distance


def update_car_velocity(street, car_a, car_b):
    street_length, deceleration_probability, max_velocity, acceleration = street
    position, velocity = car_a
    velocity = max(
        0,
        min(
            max_velocity,
            velocity + acceleration,
            get_car_distance(car_a, car_b, street_length) - 1
        ) - (random.random() < deceleration_probability)
    )
    return make_car(position, velocity)


def update_car_position(street_length, car):
    position, velocity = car
    return make_car((position + velocity) % street_length, velocity)


def make_cars(street_length, car_density):
    positions = random.sample(
        range(street_length), int(street_length * car_density)
    )
    positions.sort()
    return list(map(make_car, positions))


def cars_as_row(street_length, cars):
    row = [0] * street_length
    for position, _ in cars:
        row[position] = 1
    return row


def update_velocities(street, cars):
    return (
        update_car_velocity(street, car_a, car_b)
        for car_a, car_b in pairwise(prepend(cars[-1], cars))
    )


def update_positions(street_length, cars):
    return (update_car_position(street_length, car) for car in cars)


def make_cars_update(
    street_length, deceleration_probability, max_velocity=5, acceleration=1
):
    street = (
        street_length, deceleration_probability, max_velocity, acceleration
    )
    
    def update_cars(cars):
        return list(
            update_positions(street_length, update_velocities(street, cars))
        )
        
    return update_cars


def run_simulation(street_length, car_density, deceleration_probability):
    return iterate(
        make_cars_update(street_length, deceleration_probability),
        make_cars(street_length, car_density)
    )


def main():
    street_length = 320
    simulation_steps = run_simulation(street_length, 0.35, 0.3)
    
    step_count = 256
    print(f'P1\n{street_length} {step_count}\n')
    for cars in take(step_count, simulation_steps):
        print(''.join(map(str, cars_as_row(street_length, cars))))


if __name__ == '__main__':
    main()
Während ein einzelnes Auto als Tupel modelliert noch gehen mag, finde ich das bei den vier Werten für die Simulation (`street`) schon recht grenzwertig. Da hätte ich schon den Hang mit `collections.namedtuple()` einen eigenen Datentyp für zu erstellen und wenn man den erst einmal hat, liegt es auch nahe den mit Methoden zu erweitern und dann geht es auch schon Richtung OOP. Python ist halt von Grund auf eine objektorientierte Programmiersprache. Wenn man sich dagegen wehrt hat man nicht einmal irgend einen anderen Verbunddatentyp, denn Klassen sind dafür in den meisten Fällen das geeignete Mittel. Sonst endet man irgendwann mit ”parallelen” Listen und/oder magischen, undurchsichtigen Indexwerten wie in alten BASIC-Dialekten die keinen Verbunddatentyp bieten. In meiner Programmiererlaufbahn waren das CBM BASIC auf dem C64 und GW-BASIC unter DOS. QBasic/QuickBasic unter DOS hatte dann mit TYPE … END TYPE schon eine Möglichkeit eigene Verbunddatentypen zu definieren.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Um das mit den alten BASIC-Dialekten mal zu illustrieren, hier die Simulation in CBM BASIC V2 für den C64:

Code: Alles auswählen

   10 REM@ £PROTOCOL:£FASTFOR:£SHORTIF:£FASTARRAY
   20 REM@ £CONSTANT SL,SC,DP,MV,A,CD
   30 REM@ £WORD I=FAST,J=FAST,CC,P,CP(,BP:£INTEGER D
   40 REM@ £BYTE Y,V,CV(,R(,BO:£BOOLEAN F
  100 SL=320:SC=200:DP=0.3:MV=5:A=1:CD=0.35:DIM CP(SL),CV(SL),R(SL)
  110 PRINT"CREATE AND PLACE CARS...":GOSUB 5000
  120 REM VIDEORAM @ $4400, BITMAP @ $6000
  130 POKE 56576,PEEK(56576) AND 252 OR 2:POKE 53272,24:POKE 53265,59
  140 FOR I=17408 TO 18408:POKE I,15:NEXT
  200 BP=24576:BO=0
  210 FOR Y=0 TO SC-1:GOSUB 500:GOSUB 1000:NEXT:POKE 198,0:WAIT 198,1:GOTO 200
  500 REM ******************************
  510 REM ONE SIMULATION STEP.
  520 REM
  530 REM 1. UPDATE VELOCITIES.
  540 FOR I=0 TO CC:J=I+1:IF I=CC THEN J=0
  550 V=CV(I)+A:D=CP(J)-CP(I)-1:IF D<0 THEN D=D+SL
  560 IF V>D THEN V=D
  570 IF V>MV THEN V=MV
  580 IF V>=1 THEN V=V+(RND(1)<DP)
  590 CV(I)=V:NEXT
  700 REM 2. UPDATE POSITIONS.
  710 FOR I=0 TO CC:P=CP(I)+CV(I):IF P>=SL THEN P=P-SL
  720 CP(I)=P:NEXT:RETURN
 1000 REM ******************************
 1010 REM PLOT ROW.
 1020 REM
 1030 FOR I=0 TO SL-1:R(I)=0:NEXT:FOR I=0 TO CC:R(CP(I))=1:NEXT
 1040 FOR I=0 TO SL-1 STEP 8:B=0:FOR J=0 TO 7:B=B*2+R(I+J):NEXT
 1050 POKE BP+I+BO,B:NEXT:BO=BO+1:IF BO<8 THEN RETURN
 1060 BP=BP+SL:BO=0:RETURN
 5000 REM ******************************
 5010 REM CREATE CARS.
 5020 REM
 5030 CC=INT(SL*CD)-1:FOR I=0 TO SL-1:CP(I)=I:NEXT
 5040 FOR I=0 TO SL-1:J=INT(RND(1)*(SL-I))+I:GOSUB 5100:NEXT
 5050 F=0:FOR I=0 TO CC-1:J=I+1:IF CP(I)>CP(J) THEN F=-1:GOSUB 5100
 5060 NEXT:IF F THEN 5050
 5070 RETURN
 5100 REM ******************************
 5110 REM SWAP CAR POSITIONS AT I & J.
 5120 REM
 5130 P=CP(I):CP(I)=CP(J):CP(J)=P:RETURN
Das läuft selbst mit dem Basic Boss kompiliert, noch ziemlich träge. Etwas unter 4 Minuten und 20 Sekunden für das 320×200 Pixel Bild.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Immmer wenn __blackjack__ hier Basic-Code hinein wirft fängt irgendwo in meinem Kopf so 80er Synthie-Musik an zu laufen und die Gebrechen werden weniger.
Wollte ich nur mal sagen.
Benutzeravatar
Perlchamp
User
Beiträge: 172
Registriert: Samstag 15. April 2017, 17:58

ich habe einmal eine Verständnisfrage zu Listen, wenn wir bereits beim Thema sind/waren:
interaktive Shell :

Code: Alles auswählen

>>> liste = [[1, 2], [3, 4]]
>>> liste2 = list(liste)
>>> liste3 = liste[:]
>>> id(liste)
2039415693256
>>> id(liste2)
2039415701640
>>> id(liste3)
2039415457608
was ist eigentlich der Unterschied zwischen liste2 und liste3, außer, dass sie unterschiedliche ids haben? Sind ja beide flache Kopien, die 'nur' einen Zeiger/Referenz auf die Items in *liste* haben, denn:

Code: Alles auswählen

>>> liste[0][0] = 100
>>> liste
[[100, 2], [3, 4]]
>>> liste2
[[100, 2], [3, 4]]
>>> liste3
[[100, 2], [3, 4]]
wer lesen kann ist klar im Vorteil ;-)
es gibt keine Probleme, sondern nur Lösungen !
Bildung ist die Freude auf mich selbst !
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Perlchamp: Ausser das es verschiedene aber gleiche Objekte sind, gibt es keinen Unterschied.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Ja, es gibt verschiedene Arten, wie man Kopien von Listen machen kann. Das Ergebnis ist jeweils das selbe.
Benutzeravatar
Perlchamp
User
Beiträge: 172
Registriert: Samstag 15. April 2017, 17:58

danke für die schnelle(n) Antwort(en).
Das heißt, wenn die Originalliste nur unveränderbare Items (Tupel, Strings, Zahlen) beinhaltet, dann ist

Code: Alles auswählen

liste1 = list(liste)
liste2 = liste[:]
für eine Kopie aureichend, ansonsten

Code: Alles auswählen

import copy
liste3 = copy.deepcopy(liste)
wer lesen kann ist klar im Vorteil ;-)
es gibt keine Probleme, sondern nur Lösungen !
Bildung ist die Freude auf mich selbst !
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Perlchamp: Auch bei veränderbaren Objekten kann eine flache Kopie ausreichend sein. Das kommt halt immer darauf an wie man mit der Liste weiter verfahren will. `copy.deepcopy()` wird eher selten verwendet.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten