Änderung eines Objektwerts ändert zweiten Objektwert mit

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
Zeppelin1
User
Beiträge: 2
Registriert: Dienstag 1. Juli 2014, 14:31

Hallo Python Helden,

ich bin völliger Python-Neuling und lerne Python, in dem ich ein Spiel Schritt für Schritt nachprogrammiere.
Mein Problem: für zwei Spieler wird aus einer Klasse je ein Objekt kreiert. Wenn ich danach einen Wert nur für Spieler 1 (durch Change-Value) ändere, ändert sich der Wert trotzdem auch für Spieler 2 (obwohl er das nicht soll). Was mache ich hier falsch?
Vielen Dank im Voraus,
Zeppelin1

Code: Alles auswählen

class AccountsGameBegin:
    acc0210 = [210, "Developed Real Estate (Land Value)", 10000000]
    acc0300 = [300, "Developed Real Estate (Building Value)", 40000000]
    def Change_Value(self):
        self.acc0210[2] = self.acc0210[2] + 50000000
# Werte für zwei Spieler reinsaugen
player1 = AccountsGameBegin()
player2 = AccountsGameBegin()
# Anfangswerte für ersten Spieler abbilden
print ("Player 1:", player1.acc0210)
print ("Player 1:", player1.acc0300)
# Wert für ersten Spieler ändern
player1.Change_Value()
# Neue werte für ersten Spieler abbilden
print ("Player 1 New:", player1.acc0210)
print ("Player 1 New:", player1.acc0300)
# Werte für zweiten Spieler abbilden
print ("Player 2:", player2.acc0210)
print ("Player 2:", player2.acc0300)
BlackJack

@Zeppelin1: Du hast die Listen auf der *Klasse* definiert, damit haben alle Exemplare davon die selben Listen als Attribute. Du möchtest die Listen wahrscheinlich auf dem *Exemplar* setzten, also so das jedes seine eigenen Listen hat. Das macht man in der `__init__()`-Methode.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Du willst keine Klassen-Attribute benutzen, sondern Exemplar-Attribute:

Code: Alles auswählen

class Foo:
    bar = "klassenattribut"

a = Foo()
b = Foo()
b.bar += " geändert"
# a + b ausgeben

# vs
class Foo:
    def __init__(self):
        self.bar = "klassenattribut"

a = Foo()
b = Foo()
b.bar += " geändert"
# a + b ausgeben
Ohne den genauen Hintergrund zu kennen: Bist Du Dir sicher, dass Du für zwei solche Objekte wirklich *separate* Attribute anlegen willst? Auf mich macht das den Eindruck, als wären das prinzipiell Daten, die besser in einem Container (Dictionary‽) aufgehoben wären...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Zeppelin1: Das mit den nummerierten Attributnamen wobei die Nummer dem ersten Element in der dazugehörigen Liste entspricht, lässt mich übrigens vermuten, dass Du hier eigentlich ein Wörterbuch (`dict`) haben möchtest das Kontonummern (?) auf die entsprechenden Kontodaten abbildet. Und als nächstes dann aus den Listen eigene Datentypen machen, denn in einer Liste sollte man nur Werte gleichen (Duck)Typs speichern und nicht Werte wo die Position in der Liste die Bedeutung des Wertes festlegt. Das führt zu Programmen mit vielen undurchsichtigen magischen Indexzahlen.

Der Klassenname ist eigenartig. Es gibt eine spezielle Art von Konten für den Spielbeginn? Kann man das nicht allgemeiner modellieren?

Bezüglich der Namensschreibweisen und anderen Konventionen könntest Du mal einen Blick in den Style Guide for Python Code werfen.
Zeppelin1
User
Beiträge: 2
Registriert: Dienstag 1. Juli 2014, 14:31

Vielen Dank für Eure Tipps - ich werde sie morgen mit großer Freude implementieren!
Antworten