Attributänderung in Listen speichern

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
asdf
User
Beiträge: 3
Registriert: Freitag 8. Dezember 2017, 22:15

Hallo Leute,
seit einige Zeit bastel ich mir einen Knoten im Kopf.
Ich möchte in einer dynamisch erweiterbaren Listen
mittels .append die Änderung von Attributen / Variablen
abspeichern.
Über die interne Speicherverwaltung von Python werden
(leider) alle Referenzen auf das Attribut aktualisiert und
ich kann den Verlauf der Attributwerte im Nachgang nicht
mehr nachvollziehen.

zum Verständnis:
Ziel des Skriptes ist es, eine Skatliste nach Altenburger
Turnierregeln zu erstellen. Diese Liste enthält logischerweise
Spielnummer, Spielernamen, Spielwert usw.
Mit dieser Liste können dann die Punktverläufe während der
einzelnen Spiele nachverfolgt werden.

Die Aktualiserung der Referenzen der Attribute überschreibt
mir damit aber alle "alten" Spielstände. Das ist für meinen
Zweck aber nicht erwünscht.

Meine Ansätze
- Nutzung von temporären Variablen und Speicherung deren
Werte in der Liste und abschliessender Freigabe des Speichers
mit del()
- Hilfename von copy.deepcopy() über die gesamte Liste vor
der Aktualisierung mit einer neuen Spielrunde
haben nicht zum Ziel geführt.

Hat jemand Denkanstöße, wie ich die Problematik mit möglichst
Bordmitteln realisieren kann? Einen möglichen Umweg, über die
Abspeicherung in Dateien wollte ich nicht unbedingt nehmen.


Danke im voraus,
asdf
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist ein bisschen zu abstrakt um etwas dazu zu sagen. Grundsätzlich ist es nicht all zu schwer zb durch copy.deepcopy eine Kopie eines Spielstandes zu erzeugen, und den dann in einer Liste zu speichern.

Welchen Wert das hat OHNE auch auf Platte zu speichern erschließt sich mir aber nicht. Du willst doch offensichtlich nachvollziehbarkeit. Das impliziert in meinen Augen speichern. Denn dabei waren ja sonst alle.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nochmal ein Nachtrag: du hast ja schon selbst mit deepcopy gespielt. Der Punkt ist: damit (und anders) geht das. Das es nicht klappt für dich hat also etwas mit deiner konkreten Programmierung zu tun. Da wäre es gut zu zeigen was du tust.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

asdf hat geschrieben:Ziel des Skriptes ist es, eine Skatliste nach Altenburger
Turnierregeln zu erstellen. Diese Liste enthält logischerweise
Spielnummer, Spielernamen, Spielwert usw.
Mit dieser Liste können dann die Punktverläufe während der
einzelnen Spiele nachverfolgt werden.
Was genau ändert sich denn? Eigentlich doch nur die Punkte, oder? Die lassen sich doch leicht nachverfolgbar schreiben:

Code: Alles auswählen

def setze_punkte(self, punkte):
    self.verlauf_punkte.append(punkte)
    self.punkte = punkte
Alternativ auch mittels @property denkbar:

Code: Alles auswählen

@property
def punkte(self, pkt):
    self.verlauf_punkte.append(pkt)
    self._punkte = pkt

@punkte.getter
def punkte(self):
    return self._punkte
asdf
User
Beiträge: 3
Registriert: Freitag 8. Dezember 2017, 22:15

Hallo,
danke für die Antworten. Ich habe es schon vermutet
und gemerkt, dass ich mich etwas undeutlich ausdrücke.

Beispielbild

Dazu gibt es im derzeitigen Projektstand 2 verschiedene Klassen:

Klasse Spieler:
enthält Namen, ID, Punkte usw.
(im Bild die Spalten unter dem Spielernamen)

Klasse Runde:
enthält den aktuellen Spielwert, zusätzliche Spielinformationen
und das Endergebnis (Sieg / Niederlage -> Punkte) für den Spieler.
(im Bild die Spalten: Grundwert .. Spielwert +/-)

Die aufrufende Main-Fkt. legt die Spieler (Kl. Spieler) an und
soll die Rundenergebnisse (Kl.Runde) in einer Liste ab.

Code: Alles auswählen

if __name__ == '__main__':

    # Skatliste
    SL = []
    # Skatfreunde
    SF = []
    # Skatrunde
    SR = None

    _aktSpiel = SpielModifikation 	# eigene Klasse
    _aktSpieler = SkatSpieler	# eigene Klasse

    # Rundenzaehler
    rundenCnt = 0
    
    if True:
        SF.append (SkatSpieler ("EP"))
        while True:
            print ("Name Skatfreund ", len (SF))
            tmp_name = input ()
            if len (tmp_name) == 0:
                break
            else:
                SF.append (SkatSpieler (tmp_name))

    SR = SkatRunde (SF)
    while True:
        SR.auswertung ()
         _tmp_SL = copy.deepcopy(SL)

        if SR.fertig:
            SR.fertig = 0
            rundenCnt += 1
            _aktSpiel = copy.deepcopy(SR.spiel_)
            _aktSpieler = copy.deepcopy(SR.spieler)
            # Spielerstats aktualisieren
            # bei EP nur EP.win erhoehen
            if _aktSpieler.name == "EP":
                _aktSpieler.set_win ()
            else:  # kein EP
                if int(_aktSpiel.stats_ergebnis) < 0:
                    _aktSpieler.set_loss ()
                else:
                    _aktSpieler.set_win ()
                _aktSpieler.set_points (int(_aktSpiel.stats_ergebnis))
                # Spielerstats in Liste abspeichern
             SL = copy.deepcopy(SL)
             _tmp_SL.append ([rundenCnt, SR.spiel_, SR.spieler])
             SL = copy.deepcopy(_tmp_SL)
             
             print ("neue Runde? -> Zahl eingeben")
             _newRounde = read_dez (input ())
	     if _newRounde is None:                                        
	     	break
	     	
# print Liste	     	
    for x in range (len (SL)):
        _aktRunde = SL[x][0]
        _aktSpiel = SL[x][1]
        _aktSpieler = SL[x][2]
        print("Runde:    ", _aktRunde)
        print("Spieler:  ", _aktSpieler.name)
        print("Spiel:    ", _aktSpiel.stats_spielwert)
        print("Ergebnis: ", _aktSpiel.stats_ergebnis)
        print("win/loss: ", _aktSpieler.win, "/", _aktSpieler.loss)
        print("Gesamtpkt:", _aktSpieler.points)
        print("--------------------------")	     	
Die print Ausgabe gibt nun in jedem for - Schleifen - Durchlauf die Ergebnisse der letzten
Runde aus.
Bezogen auf das verlinkte Bild von oben, steht nun zum Beispiel bei "Amin" in den Zeilen
4 und 7: 70 Punkte und 2 Siege.

Ich hoffe damit kann man meine Problematik mehr verstehen.

Danke,
asdf
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Du musst halt in der Schleife, die die Runde sozusagen verwaltet, einbauen dass am Ende einer Runde die gewünschten Attribute der Objekte in eine Liste vermerkt werden. Jedes Element dieser Liste repräsentiert eine Runde. Das Element ist ein dict mit den Spielernamen als Schlüssel und den Attributen, die man sich merken will, als Werte. Die Attribute werden ihrerseits wieder als dict realisiert. Demnach wäre das Schema:

Code: Alles auswählen

spielverlauf = [
    {
        "Sebastian": {"attr1": 42, "attr2": "foo", ...},
        "Matthias": {"attr1": 23, "attr2": "bar", ...},
        "Annika": {"attr1": 4711, "attr2": "baz", ...}
    },
    {
        "Sebastian": {"attr1": 99, "attr2": "spam", ...},
        "Matthias": {"attr1": 11, "attr2": "ham", ...},
        "Annika": {"attr1": 45, "attr2": "eggs", ...}
    },
    ...
]
Eine mögliche Abfrage wäre dann:

Code: Alles auswählen

def gib_punkte(spielername, runde_nr):
    runde = spielverlauf[runde_nr - 1]
    return runde[spielername]["punkte"]
Dies würde ich aber wohl eher als Methode einer Klasse Spiel bauen, damit man das mit dem globalen Zustand mittels self.spielverlauf etwas sauberer gelöst hat.

Wahrscheinlich denkst du auch viel zu kompliziert. Der gezeigte Code sieht auch ziemlich hingemurkst aus. Möglichweise solltest du dein Spiel komplett neuschreiben mit den Erfahrungen, die du bisher gemacht hast. Sonst blickst du irgendwann gar nicht mehr durch (sofern du es jetzt überhaupt noch tust). Nur so als Tipp...
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

IMHO spricht hier auch einiges dafür, die Ergebnisse in einer relationalen Datenbank (wie SQLite) zu speichern. Da muss mal sich halt ein bisschen Gedanken über das Datenbank-Schema machen (wobei das im Falle von Skat sicherlich schon mal wer gemacht hat :-) ), dann ist man auch bei der Abfrage der Ergebnisse ziemlich flexibel.

Gruß, noisefloor
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@asdf: um das Programm zu verstehen und laufen lassen zu können, fehlen die Klassen `SpielModifikation`, `SkatSpieler` und `SkatRunde`.

Alles was unter `if __name__ == '__main__':` steht sollte in einer Funktion, die üblicherweise `main` genannt wird, stehen. Die Funktion hat dann auch schon eine Länge erreicht, um sie in mehrere Funktionen aufzuteilen.

SL, SR und SF sind schlechte Namen, das sieht man schon daran, dass Du einen Kommentar brauchst, der den wirklichen Namen enthält. Komplett großgeschriebene Namen sind für Konstanten reserviert, normale Variablennamen werden komplett klein geschrieben, also wird aus SL skatliste, aus SR skatrunde und SF skatfreunde. Warum enthalten andere Variablennamen führende Unterstriche? Das ist für Instanzattribute das Kennzeichen, dass sie nur intern verwendet werden sollen, für lokale Variablen ist das aber unsinnig. SR, _aktSpiel und _aktSpieler werden mit Dummy-Werten belegt, wobei bei den beiden letzten der Dummywert eine Klasse ist. Das führt dazu, falls die Variable nicht mit einem richtigen Wert belegt wird, zu seltsamem Verhalten. Variablen brauchen keinen Wert und Python meckert dann, falls es an eine Stelle kommt, wo auf die Variable zugegriffen wird.

Wer ist der Spieler EP und warum spielt er immer mit? Was soll das tmp bei `tmp_name`? `len(tmp_name) == 0` ist die umständliche Schreibweise von `not tmp_name`.

Ab dann wird es unverständlich. Du machst bei Deiner Skatrunde nur Auswertungen, ohne dass die Skatrunde jemals Informationen erhält? Was wird da ausgewertet? Warum existiert nur eine Runden-Instanz, wenn doch mehrere Runden gespielt werden können? Du machst eine Kopie des aktuellen Spiels, das aber nie geändert wird, die Kopie also überflüssig ist. In der Schleife werden Dinge gemacht, die eigentlich in den Klassen passieren sollten, z.B. das Setzen der Punkte für einen Spieler. Du machst eine Kopie von SL um sie zwei Zeilen später wieder zu überschreiben. _tmp_SL wird gar nicht gebraucht. Welche Zahl soll denn bei der Frage nach einer neuen Runde eingegeben werden? Die Rundennummer zählst Du doch unabhängig davon?

Die for-Schleife am Ende ist ein sogenanntes Anti-Pattern, weil Du über den Index, statt direkt über die Elemente der Liste SL iterierst. Vor öffnenden Klammern bei Funktionsaufrufen kommt kein Leerzeichen.

Generell, deepcopy ist eigentlich nie nötig, wenn man die Daten richtig organisiert. Man spart sich viel Ärger und Fehlerquellen, wenn man so weit wie möglich den Grundsatz „neu erzeugen“ statt „ändern“ einhält.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

So könnte es aussehen: alle notwendige Information wird in Spiel-Instanzen gespeichert, so dass man nichts (auch keine Spieler) kopieren müßte. Statistische Zahlen werden dann berechnet, wenn sie gebraucht werden.

Code: Alles auswählen

def eingabe_skatfreunde():
    skat_freunde = [SkatSpieler("EP")] # der spielt wohl immer mit
    while True:
        name = input("Name Skatfreund {}:".format(len(skat_freunde)))
        if not name:
            break
        skat_freunde.append(SkatSpieler(name))
    return skat_freunde

def ausgabe(skat_liste):
    # Gesamtpunkte werden bei der Ausgabe gezählt:
    punkte = defaultdict(int)
    wins = defaultdict(int)
    looses = defaultdict(int)
    for spiel in skat_liste:
        name = spiel.spieler.name
        ergebnis = spiel.stats_ergebnis
        punkte[name] += ergebnis
        wins[name] += ergebnis > 0
        looses[name] += ergebnis < 0
        print("Runde:    ", spiel.spiel_nummer)
        print("Spieler:  ", name)
        print("Spiel:    ", spiel.stats_spielwert)
        print("Ergebnis: ", ergebnis)
        print("win/loss: ", wins[name], "/", looses[name])
        print("Gesamtpkt:", punkte[spiel.spieler.name])
        print("--------------------------")           

def main():
    skat_freunde = eingabe_skatfreunde()
    skat_liste = []
    skat_runde = SkatRunde(skat_freunde)
    for spiel_nummer in itertools.count(1):
        spiel = skat_runde.neues_spiel(spiel_nummer)
        # das Spiel enthält den Spieler, die Punkte, etc.
        skat_liste.append(spiel)
        neue_runde = input("neue Runde? (j/n)")
        if neue_runde == 'n':
            break
    ausgabe(skat_liste)

if __name__ == '__main__':
    main()
asdf
User
Beiträge: 3
Registriert: Freitag 8. Dezember 2017, 22:15

Hallo Leute,
vielen Dank für die Antworten.
Ich habe einige eurer Ratschläge befolgt und bin noch einmal in mich gegangen.

Eine Neuprogrammierung habe ich mir schon vor dem erstem Posting durch den
Kopf gedacht. Ich wollte habe nur auf neue Anregungen gewartet.
Hauptschwerpunkt des Rewrite waren Basisfunktionen, wie die Speicherung von
Daten und deren Zugriff. Mathematische Berechnungen usw. wurden durch Random - Fkt.
ersetzt, ebenso wie die Spielerverwaltung und spielen keine primäre Bedeutung.

Ein paar kleine Anmerkungen noch:
- "EP" ist eine Art dummy - Spieler, der gesetzt wird, wenn keiner der anderen Spieler
die Runde spielen will und ist somit in jeder Liste "anwesend".
- Implementierung Datenbank, graf. Oberfläche usw:
Mit diesem Projekt will ich mir Python aneignen. Das hier ist der erste Schritt
um mir die allgemeinen Konzepte zur Python - Programmierung beizubringen.
Mit derartigen Features ziehe ich mir nur noch mehr Baustellen auf den Tisch und
der Code wird noch weniger verständlich. Datenbank, Visu usw. kommen, wenn dieses
Basisgerüst steht.

Wie gesagt, nachfolgender Code ist auf das notwendige reduziert. Mein Problem aus
dem ursprünglichen Posting kann nachvollzogen werden, indem die auskommentierten
Zeilen (de)kommentiert werden und die jeweiligen Zeilen darüber auskommentiert
werden. (for - Schleifen in skatliste.py).

skatliste.py:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: cp1252 -*-

import random
from collections import namedtuple

from skatrunde import SkatRunde
from skatspieler import SkatSpieler

if __name__ == "__main__":

    gewinnstufe = namedtuple("Gewinnstufe",
                             ["Hand", "Schneider", "Schneider_anges", "Schwarz", "Schwarz_anges", "Overt"])
    spieler = namedtuple("Skatspieler", ["name", "gewonnen", "verloren", "punkte"])

    skat_runde = SkatRunde()
    skat_spieler_0 = SkatSpieler("EP")
    skat_spieler_1 = SkatSpieler("SF1")
    skat_spieler_2 = SkatSpieler("SF2")
    skat_spieler_3 = SkatSpieler("SF3")
    skat_freunde = [skat_spieler_0, skat_spieler_1, skat_spieler_2, skat_spieler_3]
    skatliste = []

    for x in range(int(input("Runden? "))):
        akt_spieler = skat_freunde[random.randint(0, 3)]
        skat_runde.set_gewinnstufe_bool_random()
        skat_runde.set_grundwert_random()
        skat_runde.set_spielwert_random()
        akt_runde_gewinnstufe = gewinnstufe(skat_runde.get_gewinnstufe_hand,
                                            skat_runde.get_gewinnstufe_schneider,
                                            skat_runde.get_gewinnstufe_schneider_angesagt,
                                            skat_runde.get_gewinnstufe_schwarz,
                                            skat_runde.get_gewinnstufe_schwarz_angesagt,
                                            skat_runde.get_gewinnstufe_overt)
        akt_runde_grundwert = skat_runde.get_grundwert()
        akt_runde_spielwert = skat_runde.get_spielwert()
        if akt_spieler.get_spieler_name == "EP":
            akt_spieler.set_win()
        else:
            if akt_runde_spielwert < 0:
                akt_spieler.set_loss()
            else:
                akt_spieler.set_win()
            akt_spieler.set_points(akt_runde_spielwert)
        tmp_spieler = spieler(akt_spieler.get_spieler_name, akt_spieler.get_spieler_win, akt_spieler.get_spieler_loss, akt_spieler.get_spieler_points)
        skatliste.append([x, akt_runde_grundwert, akt_runde_gewinnstufe, akt_runde_spielwert, tmp_spieler])
        # skatliste.append([x, akt_runde_grundwert, akt_runde_gewinnstufe, akt_runde_spielwert, akt_spieler])

    for x in range(len(skatliste)):
        zeile = skatliste[x]
        runde = zeile[0]
        grundwert = zeile[1]
        gewinnstufe = zeile[2]
        spielwert = zeile[3]
        spieler_name = zeile[4]
        print(runde, grundwert, gewinnstufe, spielwert, spieler_name)
        # print(runde, grundwert, gewinnstufe, spielwert, spieler_name.get_spieler_name, spieler_name.get_spieler_win, spieler_name.get_spieler_loss, spieler_name.get_spieler_points)
 

skatrunde.py

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: cp1252 -*-

import random


class SkatRunde:
    """Klasse zur Auswertung einer Skatrunde"""
    grundwerte_farbe = {"EP": 0, "Schell": 9, "Herz": 10, "Gruen": 11, "Kreuz": 12, "Grand": 24}
    grundwerte_null = {"Null": 23, "Null-Hand": 35, "Null-Overt": 46, "Null-Hand-Overt": 59}

    def __init__(self):
        """Konstruktor / INIT"""
        self.__grundwert = self.grundwerte_farbe["EP"]
        self.__spitzen = 0
        self.__hand = False
        self.__schneider = False
        self.__schneider_angesagt = False
        self.__schwarz = False
        self.__schwarz_angesagt = False
        self.__overt = False
        self.__spielwert = 0

    @property
    def get_gewinnstufe_hand(self): return self.__hand

    @property
    def get_gewinnstufe_schneider(self): return self.__schneider

    @property
    def get_gewinnstufe_schneider_angesagt(self): return self.__schneider_angesagt

    @property
    def get_gewinnstufe_schwarz(self): return self.__schwarz

    @property
    def get_gewinnstufe_schwarz_angesagt(self): return self.__schwarz_angesagt

    @property
    def get_gewinnstufe_overt(self): return self.__overt

    def set_gewinnstufe_bool_random(self):
        """bool'sche Werte der Gewinnstufen
        zufaellig mit True / False belegen"""
        self.__hand = random.choice([True, False])
        self.__schneider = random.choice([True, False])
        self.__schneider_angesagt = random.choice([True, False])
        self.__schwarz = random.choice([True, False])
        self.__schwarz_angesagt = random.choice([True, False])
        self.__overt = random.choice([True, False])

    def get_grundwert(self):
        """Rueckgabe Integer Spielgrundwert"""
        return self.__grundwert

    def set_grundwert_random(self):
        """Grundwert (int) zufaellig
        zwischen 0 .. 72 setzen"""
        self.__grundwert = random.randint(0, 72)

    def get_spielwert(self):
        """Rueckgabe Integer Spielwert / Punkte"""
        return self.__spielwert

    def set_spielwert_random(self):
        """Spielwert (int) zufaellig
        zwischen -200..144 setzen"""
        self.__spielwert = random.randint(-200, 144)

skatspieler.py:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: cp1252 -*-


class SkatSpieler:
    def __init__(self, name: str= "Skatfreund") -> object:
        self.__name = name
        self.__id = 0
        self.__win = 0
        self.__loss = 0
        self.__points = 0

    def set_win(self): self.__win += 1

    def set_loss(self): self.__loss += 1

    def set_points(self, value): self.__points += value

    def set_edit_abs(self, win, loss, points):
        self.__win = win
        self.__loss = loss
        self.__points = points

    def set_edit_rel(self, win, loss, points):
        self.__win += win
        self.__loss += loss
        self.__points += points
        
    @property
    def get_spieler_name(self): return self.__name
    
    @property
    def get_spieler_win(self): return self.__win
    
    @property
    def get_spieler_loss(self): return self.__loss
    
    @property
    def get_spieler_points(self): return self.__points
    
Danke
für evtl. Anregungen,
asdf
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ein paar Anmerkungen:

Code: Alles auswählen

for i in range(len(liste)):
      ding = liste[i]
ist ein Anti-Pattern. In Python iteriert man direkt ueber das iterable:

Code: Alles auswählen

for ding in liste:
      ...

Braucht man einen Index dazu, dann erzeugt man sich den mit enumerate:

Code: Alles auswählen

for i, ding in enumerate(liste, start=1):
      ...
Hat wie man sieht den Vorteil, das man auch einen Index ab 1 (oder einer anderen Zahl) erzeugen kann, falls das zB fuer eine Text-generierung mit Aufzaehlung verwandt werden soll.

Benutze gleich Tupel-Unpacking, wenn du immer gleich viele Dinge hast:

Code: Alles auswählen

for hund, katze, maus in tiernamen:
     ...
Das es den doppelten Unterstrich gibt vergiss bitte sofort wieder. Der ist *NICHT* dafuer gedacht, Dinge 'privat' zu machen. Sondern Namenskollisionen zu verhindern. Und verursacht subtile Fehler, wenn man ihn nicht genau versteht. Wenn etwas privat sein soll, dann kennzeichne das mit nur einem Unterstrich. Wenn du dann auch noch einen trivialen getter dafuer baust (extra zwei Zeilen Code..), ob als property oder Methode, dann spar dir den Aufwand, und benutz einfach zB spieler.name direkt, ohne Unterstrich, ohne getter, ohne setter.

Eine Methode wie "set_win" ist schlecht benannt, sie impliziert, das man etwas *setzt*, also einen beliebigen Wert setzen kann. Du incrementierst aber nur. Zwei Attribute "_wins" und "_losses", sowie Methoden "win()" und "lose()" machen das klarer.

Auch die ganzen get_* vor properties sind unueblich (siehe oben, das man das gar nicht braucht, doch wenn es ein property sein soll..) dann sollte es ohne einen solchen Prefix geschrieben werden. *Wenn* solle get_irgendwas() eine Methode, kein property sein. Das property heisst ja nach dem Ding, das es darstellt, nicht nach der Taetigkeit es zu holen.

Durch diese Massnahmen schrumpft deine SkatSpieler-Klasse um mindestens die Haelfte. Wieviel Sinn es macht, einen Defaultnamen fuer einen Spieler zu vergeben erschliesst sich mir nicht. Wenn du das wirklich willst, dann sollte das statt "Skatfreund" None sein, und im Konstruktor pruefst du dann auf None, und generierst einen eindeutigen Name:

Code: Alles auswählen

if name is None:
    name = "Skatfreund {}".format(next(self.name_counter))
mit name_counter als itertools.count() als Klassenatribut.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@asdf: noch zusätzlich zu dem was __deets__ schreibt. Eine Datei pro Klasse ist übertrieben, das macht man vielleicht in Java, weil man dazu gezwungen wird. Pack das ganze Spiel in eine Datei. Auch Klassenkonstanten werden groß geschrieben, also GRUNDWERTE_FARBE oder GRUNDWERTE_NULL. `__init__` ist kein Konstruktor sondern ein Initialisierer. Nach einem Doppelpunkt fängt immer eine neue Zeile an. Eine ID, die nie gesetzt wird, ist überflüssig. Die set_xxx_random-Methoden sind irgendwie komisch. Wenn Du Dir Test-Daten erzeugen willst, mach das in einer extra Funktion, und die Werte sollten dann auch sinnvoll sein.

In Main: alles was nach `if __name__ == '__main__':` steht solte in eine Funktion wandern, die üblicherweise `main` genannt wird, und nur diese wird im if aufgerufen. Namedtuple sind Klassen, sollten also auch auf oberster Ebene definiert und groß geschrieben werden: Gewinnstufe. Das erzeugen der Gewinnstufe ist eine Methode der SkatRunde. Funktionen sollte man auch aufrufen ().
Antworten