Problem innerhalb Klasse mit Listen übergabe

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
Medds
User
Beiträge: 27
Registriert: Samstag 17. Oktober 2020, 19:19

Hallo.
Bin neu hier in diesem Forum.
Hoffe die Frage ist für die Profis hier nicht zu unsinnig, aber ich finde trotz google und co keine Erklärung die meine Denkblockade löst.

Ich habe folgendes Problem:
Ich habe eine Klasse deren Funktionen funktionieren wenn ich sie nicht in eine Klasse packe.
Ich möchte die Liste "kartendeck" von Methode 1 in der Methode 2 verwenden, aber trotz zahlloser versuche bin ich zu blöd dazu.
Bin kein Schüler der seine Hausaufgaben lösen möchte (wie es im Forum steht), sondern ein 37 Jähriger Messmaschinien Programmierer der das nebenbei lernen möchte.
Mein Programmieren am Arbeitsplatz hat aber nichts im entferntesten mit einer Programmiersprache wie Python zu tun. Das nur zur Info über mich.
Also erst mal der code den ich bis jetzt habe:

class Karten:

def karten_erstellen(self):
farben = ['Herz', 'Karo', 'Pik', 'Kreuz']
werte = ['7', '8', '9', '10', 'Bube', 'Dame', 'König', 'Ass']

kartendeck = []

for w in farben:
for y in werte:
z = str(w + ' ' + y)
kartendeck.append(z)
return kartendeck

def karten_zuweisen(self):
kartendeckcopy = kartendeck.copy()
z_ass = 1
z_7 = 7
z_8 = 8
z_9 = 9
z_10 = 10
for i in kartendeckcopy:
if '7' in i:
i_neu = i
i_neu = (i_neu, z_7)
kartendeck.append(i_neu)
kartendeck.remove(i)
for i in kartendeckcopy:
if '8' in i:
i_neu = i
i_neu = (i_neu, z_8)
kartendeck.append(i_neu)
kartendeck.remove(i)
for i in kartendeckcopy:
if '9' in i:
i_neu = i
i_neu = (i_neu, z_9)
kartendeck.append(i_neu)
kartendeck.remove(i)
for i in kartendeckcopy:
if '10' in i:
i_neu = i
i_neu = (i_neu, z_10)
kartendeck.append(i_neu)
kartendeck.remove(i)
for i in kartendeckcopy:
if 'Bube' in i:
i_neu = i
i_neu = (i_neu, z_10)
kartendeck.append(i_neu)
kartendeck.remove(i)
for i in kartendeckcopy:
if 'Dame' in i:
i_neu = i
i_neu = (i_neu, z_10)
kartendeck.append(i_neu)
kartendeck.remove(i)
for i in kartendeckcopy:
if 'König' in i:
i_neu = i
i_neu = (i_neu, z_10)
kartendeck.append(i_neu)
kartendeck.remove(i)
for i in kartendeckcopy:
if 'Ass' in i:
i_neu = i
i_neu = (i_neu, z_ass)
kartendeck.append(i_neu)
kartendeck.remove(i)

return kartendeck


def __init__(self):

karten = self.karten_zuweisen()


karten = Karten()

Wäre äußerst dankbar wenn mir jemand helfen könnte
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

Problem ist, dass die Klasse `Karten` gar keinen Zustand hat, Und wahrscheinlich auch nie einen haben wird. Bleib bei Funktionen, und übergibt die Liste der Karten als Argument.

Konstanten schreibt man komplett gross. w ist ein schlechter Name für eine Farbe und y für einen Wert und z für eine Karte.

Code: Alles auswählen

FARBEN = ['Herz', 'Karo', 'Pik', 'Kreuz']
WERTE = ['7', '8', '9', '10', 'Bube', 'Dame', 'König', 'Ass']

def karten_erstellen():
    kartendeck = []

    for farbe in FARBEN:
        for wert in WERTE:
            karte = f"{farbe} {wert}"
            kartendeck.append(karte)
    return kartendeck
Statt Listen zu verändert erzeugt man eine neue Liste. Dann braucht man auch keine Listen zu kopieren. Statt acht mal die selbe Schleife zu kopieren, würde man eine Schleife programmieren.

Code: Alles auswählen

ZAHLENWERTE = {'7': 7, '8': 8, '9': 9, '10': 10, 'Bube': 10, 'Dame': 10, 'König': 10, 'Ass': 1}
def karten_zuweisen(kartendeck):
    kartendeck_mit_zahlenwert = []
    for wert, zahl in ZAHLENWERTE.items():
        for karte in kartendeck:
            if wert in karte:
                kartendeck_mit_zahlenwert.append((karte, zahl))
    return kartendeck_mit_zahlenwert
Das ist aber sehr umständlich, weil man da gar keine zwei verschachtelte Schleifen braucht:

Code: Alles auswählen

def karten_zuweisen(kartendeck):
    kartendeck_mit_zahlenwert = []
    for wert, zahl in ZAHLENWERTE.items():
        wert = karte.split()[1]
        zahl = ZAHLENWERTE[wert]
        kartendeck_mit_zahlenwert.append((karte, zahl))
    return kartendeck_mit_zahlenwert
Ist aber auch noch umständlich, weil man das ja gleich von anfang an richtig erzeugen könnte:

Code: Alles auswählen

def karten_erstellen():
    kartendeck = []
    for farbe in FARBEN:
        for wert, zahl in ZAHLENWERTE.item():
            karte = (f"{farbe} {wert}", zahl)
            kartendeck.append(karte)
    return kartendeck
oder kurz:

Code: Alles auswählen

def karten_erstellen():
    return [(f"{farbe} {wert}", zahl)
        for farbe in FARBEN
        for wert, zahl in ZAHLENWERTE.item()
    ]
Medds
User
Beiträge: 27
Registriert: Samstag 17. Oktober 2020, 19:19

WOW
Super Erklärung. Danke

Hab zwar einige Zeit gebraucht bis ich alles verstanden habe. Dr. Google machts möglich. Und es wird auch noch etwas Übung erfordern bis ich das selbst so kurz und knackig anwenden kann, aber nochmal vielen vielen Dank.
Eine kurze Anmerkung hab ich: Ich glaub bei den letzten beiden .item fehlt ein s. :)
Ich werd mir das alles zu Herzen nehmen und umdenken wie ich das machen möchte, aber trotzdem (ich hoffe ich nerve nicht) möchte ich mein ursprüngliches Problem verstehen um Klassen besser zu verstehen zu lernen.
Hier ein anderes Beispiel:
Ich weiß das es nicht funktioniert und hätte auch schon einiges probiert um das a zu übergeben aber leider verstehe ich es nicht.

Code: Alles auswählen

class Test:
    def test_methode1(self):
        print("Ich bin die erste Methode")
        a = "zweite"
    def test_methode2(self):
        print(f"Ich bin die {a} Methode")
    def __init__(self):
        test2 = self.test_methode2()
Gibt es da keinen Weg in der Art oder (was ich eher glaube) kapier ich es einfach nicht?

Nochmal vielen Dank dafür dass du mir das so schön Schritt für Schritt erklärt hast. Soviel Zeit hat noch keiner geopfert mir das zu erklären.
Benutzeravatar
snafu
User
Beiträge: 6870
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

__init__() gehört immer an den Anfang und bringt die Klasseninstanz in einen nutzfähigen Zustand, d.h. es werden an der Stelle bereits alle Attribute initialisiert und ggf ein paar kleinere Vorarbeiten automatisch veranlasst. Am Ende etwas zu initialisieren, ergibt auch recht wenig Sinn, oder?

Auf "a" kannst du in der anderen Methode nicht zugreifen, weil es ein lokaler Name ist und somit nur innerhalb der test_methode1() sichtbar ist. Um das methodenübergreifend zu nutzen, musst du entweder "a" als Parameter übergeben oder (bei Klassen meist sinnvoller) "self.a" definieren und entsprechend nutzen.
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

Du rufst test_methode1 gar nicht auf, außerdem ist `a` einfach nur eine lokale Variable. `test_methode2` liefert nichts zurück, da ist das Zuweisen an `test2` unsinnig, zudem wird die lokale Variable auch nicht weiter benutzt.
__init__ ist dazu da, allen Zustand des Objekts zu initalisieren. Da muß man also alle Attribute, die andere Methoden brauchen, anlegen.
Das ganze Beispiel hat für mich keinen Sinn, so dass es auch schwierig ist, daran etwas zu verbessern. Hier mal, wie eine Klasse aussehen sollte:

Code: Alles auswählen

class Test:
    def __init__(self, a):
        self.a = a
    def test_methode2(self):
        print(f"Ich bin die {self.a} Methode")

test = Test("zweite")
test.test_methode2()
Medds
User
Beiträge: 27
Registriert: Samstag 17. Oktober 2020, 19:19

Danke ich glaube jetzt hab ich meinen Denkfehler gerafft.
Ich wollte eine Klasse mir mehereren Funktionen verwenden damit es aufgräumter ist.
Also das ich eine Klasse aufrufe und die dann mehrere Funktionen nacheinander abspult.
Aber dafür sind Klassen nicht da.
Klassen sind dafür da um Methoden zu konstruieren die in verschiedenen Situationen verwendet werden können.
Hab ich das jetzt einigermaßen richtig verstanden?
Antworten