Python **kwargs für Vererbung bei Klassen?

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Erst mal, was macht **kwargs (Keyword Arguments). Das ist eine Möglichkeit um Funktionen eine variable Anzahl von named parameters zu übergeben. So kannst du eben gut flexibel optionale Parameter übergeben. Ich persönlich finde es ein eher unschönes Pattern, in Fällen wie diesem ermöglicht es aber, dass du der Basisklasse flexibel Argumente übergibst ohne die Signatur der Funktion zu ändern.

Angenommen du hast etwa einen optionalen Parameter für die Hintergrund Farbe des Spiels. Deine erweiterte Klasse kann diese Argumente dann problemlos an die Basisklasse übergeben ohne sie irgendwo explizit deklarieren zu müssen.

Für solche eher elementaren Fragen oder Erklärungen zu Code kannst du übrigens auch super Chat GPT nutzen. Das ist eine Sache die es sehr gut kann.

CodeSnake 
Fragesteller
 19.04.2023, 21:43

Erst mal danke.

Für solche eher elementaren Fragen oder Erklärungen zu Code kannst du übrigens auch super Chat GPT nutzen. Das ist eine Sache die es sehr gut kann.
Das habe ich übrigens schon ganz oft versucht. Hat mir aber keine so hilfreiche Antwort gegeben.
0
BeamerBen  19.04.2023, 21:47
@CodeSnake

Also GPT4, also das verbesserte Modell was du in der Premium Version hast, hat mir mit deinem Fragetext und Code eine relativ gute Antwort generiert.

Kann ich ja auch mal hier rein pasten:

In Python sind **kwargs (Keyword Arguments) eine Möglichkeit, einer Funktion eine variable Anzahl von benannten (Schlüsselwort-)Argumenten zu übergeben. Sie werden häufig in Funktionen und Methoden verwendet, um mehr Flexibilität bei der Übergabe von Argumenten zu ermöglichen. **kwargs sammelt alle zusätzlichen Schlüsselwort-Argumente, die nicht explizit in der Funktionssignatur definiert sind, in einem Dictionary.

In dem von Ihnen bereitgestellten Codebeispiel wird **kwargs in der __init__-Methode der Klasse HangmanGame verwendet. Hier ermöglicht es die Übergabe zusätzlicher benannter Argumente, die in der Signatur der __init__-Methode nicht aufgeführt sind.

Die super().__init__(**kwargs) Zeile in der __init__-Methode von HangmanGame verweist auf die __init__-Methode der Basisklasse BoxLayout. Durch das Weitergeben von **kwargs stellt die Klasse HangmanGame sicher, dass alle zusätzlichen Schlüsselwort-Argumente, die beim Erstellen einer Instanz von HangmanGame bereitgestellt werden, auch an die Basisklasse BoxLayout weitergegeben werden. Dies ermöglicht es, die Eigenschaften der Basisklasse zu konfigurieren, ohne die __init__-Methode von HangmanGame explizit zu ändern.

Ein Beispiel: Angenommen, Sie möchten beim Erstellen einer Instanz von HangmanGame die Hintergrundfarbe der BoxLayout-Klasse ändern. Sie könnten dies tun, indem Sie das Schlüsselwort-Argument background_color an den Konstruktor übergeben, wie folgt

hangman_game = HangmanGame(background_color=(1, 0, 0, 1))

Da die __init__-Methode von HangmanGame **kwargs an die __init__-Methode der Basisklasse BoxLayout weitergibt, wird die Hintergrundfarbe entsprechend geändert, ohne dass Sie die __init__-Methode von HangmanGame ändern müssen.

Zusammengefasst ermöglicht **kwargs in diesem Code eine flexiblere und erweiterbare Art der Vererbung, indem es dem Benutzer ermöglicht, zusätzliche benannte Argumente an den Konstruktor der Basisklasse zu übergeben, ohne die __init__-Methode der abgeleiteten Klasse zu ändern.

1
CodeSnake 
Fragesteller
 19.04.2023, 22:12
@BeamerBen

Danke. Ich habe leider keinen Premiumaccount. Diese Antwort von GPT-4 ist aber in der Tat echt gut.

0
CodeSnake 
Fragesteller
 19.04.2023, 22:15
@CodeSnake

Die Antwort war entscheidend. Jetzt hat es bei mir „Klick“ gemacht. Vielen Dank.

0

Also, **kwargs ist ein spezielles Argument in Python, das es erlaubt, beliebige benannte Argumente an eine Funktion weiterzugeben. Das bedeutet, dass man der Funktion zusätzliche Argumente übergeben kann, ohne dass man vorher genau wissen muss, welche Argumente das sind.

In diesem konkreten Beispiel wird das **kwargs-Argument in der init-Methode der Klasse HangmanGame verwendet, um sicherzustellen, dass alle benannten Argumente, die an die HangmanGame-Instanz übergeben werden, an die init-Methode der übergeordneten Klasse (BoxLayout) weitergeleitet werden. Dadurch können zusätzliche Argumente an die BoxLayout-Klasse weitergegeben werden, ohne dass man sich darum kümmern muss, welche Argumente das genau sind.

CodeSnake 
Fragesteller
 19.04.2023, 18:32

Also damit man HangmanApp.run(level=3, points=6, etc.) schreiben kann?
Wenn das der Zweck ist, frage ich mich nämlich, warum man das beim Instanziiern macht und die Argumente „level“ und „points“ nicht einfach in die __init__() Methode von HangmanGame() schreibt. Also zu „word_list“, „guessed_letters“ etc.

1
Anonym13592  19.04.2023, 18:34
@CodeSnake

Ja genau! :)
In diesem - ich nenne es mal: speziellen Fall - / Beispiel gibt es wahrscheinlich einen anderen Grund, warum **kwargs verwendet wird. Es ist möglich, dass die HangmanGame-Klasse in einem anderen Teil des Programms von einer anderen Klasse abgeleitet wird, die zusätzliche Argumente verwendet. Wenn man **kwargs verwendet, kann man sicherstellen, dass alle benannten Argumente an die übergeordnete Klasse (BoxLayout) weitergeleitet werden, ohne dass man jedes Mal explizit die Namen der Argumente angeben muss - lässig.

Man könnte die Argumente auch direkt in die init-Methode von HangmanGame schreiben, aber das könnte ein Problem darstellen, wenn sich die benannten Argumente in Zukunft ändern oder erweitert werden. Wenn man **kwargs verwendet, ist die HangmanGame-Klasse flexibler und kann benannte Argumente akzeptieren, die sie vielleicht nicht kennt oder die in Zukunft hinzugefügt werden (im Code etc)

2
CodeSnake 
Fragesteller
 19.04.2023, 18:41
@Anonym13592

Vielen Dank. Ich hab das nämlich erst echt nicht verstanden. Ich bin erst 14 und will für eine Informatikprojektarbeit eine Kivy App programmieren. Sie haben mir sehr geholfen.

1
BeamerBen  19.04.2023, 21:39

Respekt, hätte die Chat GPT Antwort nicht erkannt, hätte ich es nicht selber da rein gepasted :p

(finds aber hier auch okay, da du offensichtlich selber genug Ahnung hast um den Text auch zu verifizieren und nicht einfach nur blind pastest).

0
Anonym13592  19.04.2023, 21:49
@BeamerBen

GPT spuckt dabei (denke ich) nicht verständliche Antworten aus. Habs hier mal selbst übernommen. Hätte die Quellen verlinken sollen, jetzt ist aber der Verlauf schon weg und die Sache gegessen.

1

Das sind doch die Argumente die der Funktion übergeben werden können

https://www.data-science-architect.de/args-kwargs/

CodeSnake 
Fragesteller
 19.04.2023, 21:13

Ja. Aber wozu braucht man dass, wenn man etwas vererbt?

0
NackterGerd  19.04.2023, 21:19
@CodeSnake

Es sollen in der Vererbung ja alle Agumente genauso übernommen werden und dort evtl noch erweitert werden können

1
CodeSnake 
Fragesteller
 19.04.2023, 21:21
@NackterGerd

Noch eine Frage. Ich weiß jetzt , dass **kwargs in meinem Falle hierfür ist:
“Also damit man HangmanApp.run(level=3, points=6, etc.) schreiben kann“.
Aber wozu muss man die überhaupt an die übergeordnete Klasse weitergeben?

0
NackterGerd  19.04.2023, 21:28
@CodeSnake

Dazu müsste man den ganze Code sehen um zu verstehen was er mit den Parametern macht

0
CodeSnake 
Fragesteller
 19.04.2023, 21:38
@NackterGerd

Hier ist der ganze Code in zwei Teilen:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.image import Image
from kivy.core.window import Window
import random


class HangmanGame(BoxLayout):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.word_list = ["python", "java", "ruby", "javascript", "php"]
        self.guess_word = []
        self.secret_word = ""
        self.remaining_guesses = 6
        self.img_path = "img/hangman_{}.png"
        self.create_game_layout()
        self.new_game()

    def create_game_layout(self):
        self.orientation = "vertical"
        self.image = Image(source=self.img_path.format(0))
        self.word_label = Label(text=" ".join(self.guess_word),
                                font_size="50sp",
                                halign="center",
                                valign="middle")
        self.remaining_guesses_label = Label(text=f"Remaining guesses: {self.remaining_guesses}")
        self.input_label = Label(text="Enter a letter:")
        self.input = TextInput(multiline=False)
        self.submit_button = Button(text="Submit", on_press=self.check_letter)
        self.add_widget(self.image)
        self.add_widget(self.word_label)
        self.add_widget(self.remaining_guesses_label)
        self.add_widget(self.input_label)
        self.add_widget(self.input)
        self.add_widget(self.submit_button)
0
CodeSnake 
Fragesteller
 19.04.2023, 21:39
@CodeSnake
def new_game(self):
        self.secret_word = random.choice(self.word_list)
        self.guess_word = ["_"] * len(self.secret_word)
        self.remaining_guesses = 6
        self.image.source = self.img_path.format(0)
        self.input.text = ""
        self.word_label.text = " ".join(self.guess_word)
        self.remaining_guesses_label.text = f"Remaining guesses: {self.remaining_guesses}"

    def check_letter(self, instance):
        letter = self.input.text
        if letter in self.secret_word:
            for i, c in enumerate(self.secret_word):
                if c == letter:
                    self.guess_word[i] = letter
            if "_" not in self.guess_word:
                self.end_game(True)
        else:
            self.remaining_guesses -= 1
            self.image.source = self.img_path.format(6 - self.remaining_guesses)
            self.remaining_guesses_label.text = f"Remaining guesses: {self.remaining_guesses}"
            if self.remaining_guesses == 0:
                self.end_game(False)
        self.input.text = ""
        self.word_label.text = " ".join(self.guess_word)

    def end_game(self, victory):
        message = "Congratulations, you won!" if victory else f"Sorry, the word was {self.secret_word}."
        self.remaining_guesses_label.text = message
        self.remove_widget(self.input_label)
        self.remove_widget(self.input)
        self.remove_widget(self.submit_button)
        self.add_widget(Button(text="New Game", on_press=self.new_game))


class HangmanApp(App):

    def build(self):
        Window.clearcolor = (0.5, 0.5, 0.5, 1)
        return HangmanGame()


if __name__ == '__main__':
    HangmanApp().run()


0
NackterGerd  19.04.2023, 21:45
@CodeSnake

Du hast doch nach der Vererbung geredet.

Ich dachte die Vererbung von Boxlayout?

Tut mir leid jetzt verstehe ich gar nicht mehr was du willst

Tut mir leid

0