**kwargs in __init__() Methode und "self" in Python?

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

super() ist die Elternklasse von der ererbt wurde, also GridLayout.

kwargs sind keyword(ed) args, also benannte Argumente, wenn Du also beim Aufruf sowas wie n=5 übergibst. Es wird also nicht nach Position (positional) sondern nach Name (name/keyword) übergeben.

Dein Konstruktor (Ctor) nimmt also die keyword args und reicht sie an die Elternklasse durch (**kwargs bezeichnet hier die Gesamtheit aller via Name übergebenen Argumente):

super().__init__(**kwargs)

Rufe Konstruktor der Elternklasse mit keyworded arguments auf.

P.S.: der erste Parameter einer Methode ist eine Referenz auf die Objektinstanz, also das aktuelle Objekt.

P.P.S.: Technisch ist es etwas komplexer, weil die * eigentlich ein packing/unpacking machen, aber das solltest Du Dir vielleicht in Ruhe mal zu Gemüte führen.

CodeSnake 
Fragesteller
 10.04.2023, 13:54

Sehr gute Antwort! Und einfach am besten erklärt. Das war eine riesen Hilfe.

0
Aber wieso kann man aus einer Methode auf die Instanzvariablen nur zugreifen, wenn vor diesen "self" steht?

Der Parameter self verweist auf das Objekt und nur das kennt seine an ihm gebundenen Attribute.

Angenommen, du hast diese Anwendung:

class Person:
  def __init__(self, name):
    self.name = name

  def say_name(self):
    print(self.name)

person = Person("Max")
person.say_name()

Ein Objekt vom Typ Person wird erstellt und an dieses ein Attribut name gebunden. Der Aufruf von say_name ist implizit nichts anderes, als ein normaler Funktionsaufruf, bei dem allerdings das Objekt übergeben wird:

say_name(person)

Dieses Objekt wird an den Parameter self gegeben. Gäbe es den Parameter nicht, gäbe es keinen Bezug zum Objektkontext.

Und meine zweite Frage ist, wozu bei der Initialisierung der __init__() Methode manchmal noch so ein **kwargs steht.

Das erlaubt die Übergabe beliebig vieler, benannter Parameter.

Dieses spezielle Parameterfeature kann im Grunde für jede normale Funktion angewandt werden:

def print_data(**arguments):
  for key, value in arguments.items():
    print(key, value)

print_data(age=82, name="Pete", location="New York")

In deinem Fall dient es dazu, genauso flexibel Argumente aufnehmen zu können, wie auch der Basistyp (GridLayout).

Ach ja. Was dieses "super()" bedeutet habe ich auch nicht so ganz verstanden.

Damit wird auf den Basistyp GridLayout zugegriffen.

Angenommen, du möchtest ein Grid Layout mit drei Spalten und drei Reihen anlegen. Dafür kannst du so vorgehen:

layout = GridLayout(cols=3, rows=3)

da der GridLayout-Typ einen Konstruktor besitzt, der die Übergabe benannter Parameter erlaubt.

Nun hast du dir aber einen eigenen Typ erstellt, der von GridLayout erbt. Der kann bei dieser Implementation:

class MyGrid(GridLayout):
  def __init__(self):
    # do something ...

erst einmal noch nicht das bieten, was du oben beim normalen GridLayout-Typ nutzen konntest: Du kannst beim Anlegen nicht direkt die Spalten- und Zeilenanzahl angeben. Dafür müssen die Parameter erst übergeben werden.

Restriktiv könnte man erst einmal so vorgehen:

class MyGrid(GridLayout):
  def __init__(self, cols, rows):
    super().__init__(cols=cols, rows=rows)

layout = MyGrid(3, 3)

Die super-Funktion greift auf den Basistyp zu und ruft dessen Konstruktor auf, um die beiden Werte zu übergeben.

Soweit würde dein Typ aber auch nur ein Setup mit Spalten und Zeilen erlauben. Weitere Werte, die schon beim Anlegen eines Grid Layouts definiert werden könnten (z.B. Abstände zwischen den einzelnen Zellen), werden noch nicht unterstützt. Indem man den gleichen Konstruktor wie der Basistyp anbietet und den Parameter direkt weiterreicht, erhält man dieselbe Flexibilität wie der Basistyp.

class MyGrid(GridLayout):
  def __init__(self, **kwargs):
    super().__init__(**kwargs)

layout = MyGrid(cols=3, rows=3, spacing=5)

Also, bei den meisten OO sprachen ist "self" implizit. D.h. Du machst Operationen auf einer Objektinstanz einer Klasse. Bei Python musst Du sagen, dass die auf dem objekt operieren, "self" also "diesem Objekt". Klassenmethoden sind dann die Methoden, die nicht "self" als Parameter nehmen. kwargs sind Argumente, die als Schlüsselwort=Wert-Paare angegeben sind.