copy, unabhängige kopie

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
Tombery
User
Beiträge: 29
Registriert: Mittwoch 10. Juli 2019, 19:56

Leute ich werde verrückt.
Ich versuche nun seit einem Tag eine copy meiner Liste zu machen.
Meine 4 Spieler bekommen ihre Hände zufällig. Um das ordentlich auswerten zu können muss ich nun von einem Spieler die Hand festhalten.
Dazu ist es notwendig diese zufällig generierte Hand zu kopieren.

Weder mit copy, deepcopy, oder einfacht mit list[:] lässt sich diese Hand,sodass sie komplett unabhängig ist kopieren.

Interessant ist, dass das ganze funktioniert hat mit

a_copy = a_list[:]

damals konnte ich die P Wert auf die S Werte kopieren.
Die S Werte haben sich dabei nicht verändert, so konnte ich auch am Ende des Codes noch Statistiken mit der Anfangshand also den S Werten erstellen.
Die S Werte wurden damals nie verändert.

Jetzt muss ich die S Werte verändern und damit sind sie automatisch immer die P Werte und das obwohl ich unabhängige Kopien haben sollte.
Auch die Einführung von einer dritten Kopie, mit die ich dann nur zum verändern benutze hat nicht geholfen.

Hat jemand eine idee, warum es so schwer sein könnte unabhängige kopien zu erzeugen?
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@Tombery: ohne dass Du ein Beispiel in Code lieferst, versteht niemand, was Dein Problem ist.
Wie schon im anderen Thread geschrieben, ist das Kopieren von Datenstrukturen in Python eher unüblich, weil es genau zu solchen Problemen führt, wie Du sie jetzt hast.
Wenn Du statt dessen immer neue Listen erzeugst, wenn Du verändern möchtest, dann kann es nicht passieren, dass plötzlich irgendwo anders sich Werte ändern.
Tombery
User
Beiträge: 29
Registriert: Mittwoch 10. Juli 2019, 19:56

Die S Listen sind die Starthände, mit den P Listen wird gespielt.
Die S Werte werden für zukünftige Auswertungen gebraucht.

Code: Alles auswählen

Hände = austeilen(Deck)

S1 = Hände[0]
S2 = Hände[1]
S3 = Hände[2]
S4 = Hände[3]

hier hab ich schon alle Möglichkeiten etwas zu kopieren ausprobiert:
P1 = copy.deepcopy(S1) 
P2 = copy.deepcopy(S2)
P3 = copy.deepcopy(S3)
P4 = copy.deepcopy(S4)

#Diese Schleife soll dafür sorgen, dass die Hand von P1 fix bleibt aber er gegen andere Hände P2-P4 spielt.
while z < 5:


Die shuffle Funktion summiert mir die Hände der Spieler 2-3 und gibt sie mir zufällig sortiert wieder aus.
        Playerhands = P2_P3_P4_shuffle(S1,S2,S3,S4)		<--- **  	
        P2 = Playerhands[0]								  							 
        P3 = Playerhands[1]								
        P4 = Playerhands[2]

Dann beginnt das Spiel und die P Listen werden reduziert bis ein Gewinner feststeht.
	
	z = z + 1

Das Spiel sollte nun neu starten, wobei P1 wieder S1 ist und die anderen P2-P4 werden wieder neu definiert durch das zufällige shuffeln der S Werte.

Bei mir werden die S Listen genauso verändert wie die P Listen. Dadurch kommt es zu einem no median for empty data Fehler.


Ich weiß nicht, ob das wichtig ist aber das ganze ist eine Funktion und wird von einer Simulations Datei aufgerufen. Diese logt mit wer gewinnt mit welcher Hand wobei ich auch hier eine Schleife hab die diese Funktion oft aufruft.

** Hier habe ich das Problem, nachdem das Programm einmal richtig durchgelaufen ist, gilt für ihn P Liste = S Liste. Somit werden beim zweiten Durchgang nur die vom Karten welche den ersten Durchgang überlebt haben neu vergeben.

Die shuffle Funktion sieht so aus:

Code: Alles auswählen

def P2_P3_P4_shuffle(P1,P2,P3,P4):
    import random
    Playerhands = P2 + P3 + P4
    random.shuffle(Playerhands)

    n = 20
    i = 1

    del P2[:]
    del P3[:]
    del P4[:]
    while i <= n:
        P2.append(Playerhands.pop())
        P3.append(Playerhands.pop())
        P4.append(Playerhands.pop())

        i = i + 1

    P2.sort(reverse=True)
    P3.sort(reverse=True)
    P4.sort(reverse=True)

    return P2,P3,P4
Das wie gespielt wird ist sehr umfangreich und ich denke nicht, dass das damit etwas zu tun hat.
Zuletzt geändert von Tombery am Sonntag 28. Juli 2019, 15:11, insgesamt 2-mal geändert.
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Das was Du hier zeigst, ist nicht ausführbar, weil wesentliche Funktionen und Inputs fehlen und wesentliche Teile einfach durch Beschreibungen ersetzt wurden.
Außerdem fehlt die Stelle wo steht: "Hier habe ich ein Problem, weil ich das erwarte, dies aber habe".
Tombery
User
Beiträge: 29
Registriert: Mittwoch 10. Juli 2019, 19:56

Ich glaub ich habe meine Fehler gefunden.
Ich müsste vor meinem Fehler die Werte für P1 neu nochmals definieren.

Ich brauch also soetwas wie:

P1 = S1
P2 = S2
P3 = S3
P4 = P4

Dies darf ich jedoch nicht schreiben, da dies ja nur Referenzen sind und so wieder mir S verknüpft wird.
Ich muss den aktuellen Inhalt von den S in die Ps neu übergeben und zwar nicht als Referenz sondern als Liste welche die alten einträge von P überschreibt.

Gibt es hierfür eine Möglichkeit?
Tombery
User
Beiträge: 29
Registriert: Mittwoch 10. Juli 2019, 19:56

Ich habs nun hinbekommen

Die S Listen werden nie verändert.
Die R Listen werden am Anfang kopiert von den S Listen.
Mit den P Listen wird gespielt.

Dies sieht nun ca. so aus.

Code: Alles auswählen

 S1 = Deck[0]
    S2 = Deck[1]
    S3 = Deck[2]
    S4 = Deck[3]

    P1 = copy.copy(S1)
    P2 = copy.copy(S2)
    P3 = copy.copy(S3)
    P4 = copy.copy(S4)

    R1 = copy.copy(S1)
    R2 = copy.copy(S2)
    R3 = copy.copy(S3)
    R4 = copy.copy(S4)

    while z < 5:

        R1 = copy.copy(S1)
        R2 = copy.copy(S2)
        R3 = copy.copy(S3)
        R4 = copy.copy(S4)

        Playerhands = P2_P3_P4_shuffle(R1,R2,R3,R4)

        P2 = Playerhands[0]
        P3 = Playerhands[1]
        P4 = Playerhands[2]
Das ist so hässlich, dass sogar ich als Anfänger Augenkrebs bekomme aber nachdem mich dieser Fehler einen vollen Tage gekostet hat werde ich jetzt nicht versuchen dies auf nur P und S Liste zu reduzieren.
Aber vom Gefühl her ist die R Liste voll unnötig.
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Du willst Dir nicht helfen lassen, weil Du zu festgefahren bist, in der Art, wie Du denkst, dass es funktionieren müßte.

Wie schon geschrieben, darf man keine Listen verändern. Das `del P2[:]` ist der Fehler.
`P1` wird gar nicht benutzt, muß also auch nicht übergeben werden.
Die Funktion könnte z.B. so aussehen:

Code: Alles auswählen

def P2_P3_P4_shuffle(P2,P3,P4):
    hands = P2 + P3 + P4
    random.shuffle(hands)
    P2 = hands[:len(P2)]
    P3 = hands[len(P2):-len(P4)]
    P4 = hands[-len(P4):]
    P2.sort(reverse=True)
    P3.sort(reverse=True)
    P4.sort(reverse=True)
    return P2, P3, P4
Es gehen drei Listen rein und kommen drei neue Listen raus.

EDIT: das Kopieren vor der while-Schleife ist quatsch, weil Du das ja auch innerhalb nochmal machst.
Bei meiner Variante, bleibt ungefähr das übrig:

Code: Alles auswählen

S1, S2, S3, S4 = Deck
while z < 5:
    P1 = S1
    P2, P3, P4 = P2_P3_P4_shuffle(S2, S3, S4)
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Tombery: Das Problem das Du beschreibst kannst Du mit `deepcopy()` nicht haben. Da musst Du dann schon irgendetwas anderes falsch machen.

Bekomm das mit den Namen mal in den Griff. klein_mit_unterstrichen. Nichsts einbuchstabiges, durchnummeriertes, und nicht Englisch und Deutsch ohne das ersichtlich wird was was ist. `Hände` und `Playerhands` enthalten jeweils was? Was ist der Unterschied und wie soll der Leser das wissen?

Beide ``while``-Schleife die Du zeigst sind eigentlich keine, das sind beides ``for``-Schleifen.

Die ``del``-Aufrufe sind schon wieder der falsche Ansatz. Da erstellt man einfach *neue* Listen und versucht nicht alte wiederzuverwenden. Genau so ein Blödsinn macht am Ende Probleme.

Es ist auch totaler Unsinn da eine Schleife mit `pop()` drin zu schreiben. Da würde man einfacher jeweils 20 Elemente nehmen. Und ebenfalls Unsinnig ist es das mehr als einmal aufzurufen. Das sind beides Sachen die man mit realen Kartenspielen macht, weil das mischen was ein Mensch mit Karten durchführt ein sehr schlechter Pseudozufall ist. Im Gegensatz zu `random.shuffle()`.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Tombery
User
Beiträge: 29
Registriert: Mittwoch 10. Juli 2019, 19:56

Ich stimme euch beiden total zu. Meine art zu programmieren ist eher Pfuschen als sinnvolles schreiben. Ich hab das leider nie gelernt. Das gute an meiner Arbeit ist, dass es nicht wirklich effizient programmiert sein muss. Ich habe eine Computercluster zur Verfügung und bewege mich um die 10^8 Möglichkeiten. Diesbezüglich, solange ich nicht noch größeres vorhabe, sollte das kein Problem darstellen. Ich nehme an For Schleifen benutzt man deswegen, weil sie deutlich schneller sind. Nachdem ich alles hinbekommen habe, werde ich schauen, dass ich den Code noch verschöner und lesbarer gestallte.
Ich bin ja schon stolz darauf wie weit ich mit meinen Pfuschen gekommen bin. Alleine meine Functions Datei besitzt schon 300 Zeilen.
Da dieses Programm schon recht groß geworden ist, tue ich mir schwer die eigentlichen Probleme zu beschreiben.
Ich will niemanden zumuten sich durch meinen Jungelcode zu kämpfen.

Danke Sirius für deine Shuffel Funktion, die ist wirklich viel schöner.
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Tombery: ``for``-Schleifen benutzt man weil der Leser dann sofort weiss was da passiert ohne in der Schleife erst nachschauen zu müssen ob, wo, unter welchen Bedingungen die Variablen auf welche Art verändert werden, die an der Schleifenbedingung beteiligt sind.

Wenn Funktionen so geschrieben sind, dass sie alle Werte ausser Konstanten als Argument(e) übergeben bekommen und nichts an der Eingabe verändert, also zum Beispiel mit ``del`` alle Elemente von übergebenen Listen leeren, dann lassen sich Probleme in der Regel sehr einfach auf einzelne Funktionen eingrenzen. Genau deswegen macht man das ja so, das Funktionen möglichst keine Nebeneffekte haben.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten