pos und kw Argumente; Stern-Operator#

EN: positional argument, keyword argument

# z.B. ein flacher LEGO-Stein hat Volumen 1 Kubikzentimeter
a=0.5; b=1; c=2

positionial#

def volumen_quader(x, y, z, koerper="Quader"):
    print( f"""Meine Parameter: 
          {x=}, {y=}, {z=}, 
          {koerper=}""" )
    #print("Paramter x=", x, ", y=", y, ", z=", z, ", koerper=", koerper)
    if koerper == "Quader":
        return koerper, x*y*z # Kantenlängen
    else:
        return f"das kenne ich nicht: {koerper}", None
# reine Positionsargumente
volumen_quader(a, b, c, "quader")
Meine Parameter: 
          x=0.5, y=1, z=2, 
          koerper='quader'
('das kenne ich nicht: quader', None)
# Default-Werte
volumen_quader(a, b, c)
Meine Parameter: 
          x=0.5, y=1, z=2, 
          koerper='Quader'
('Quader', 1.0)
# unbekannte Körper bitte abfangen
volumen_quader(a, b, c, koerper="Tetraeder")
Meine Parameter: 
          x=0.5, y=1, z=2, 
          koerper='Tetraeder'
('das kenne ich nicht: Tetraeder', None)

keyword#

# Positionsargumente + keyword argument
volumen_quader(a, b, c, koerper="Quader")
Meine Parameter: 
          x=0.5, y=1, z=2, 
          koerper='Quader'
('Quader', 1.0)
# Reihenfolge vertauschen mit Keywords
volumen_quader(a, z=c, y=b, koerper="Quader" )
Meine Parameter: 
          x=0.5, y=1, z=2, 
          koerper='Quader'
('Quader', 1.0)
# nach KW-Args können keine Pos-Args mehr kommen
# das geht nicht:
#volumen_quader(a, y=b, z=c, "Quader")

allgemeinere Lösung für Volumen#

generische Lösung: Wir haben auch Kugeln!

def volumen(x, *, y=None, z=None, koerper="Kugel"):
    if koerper == "Quader":
        return koerper, x*y*z # Kantenlängen
    elif koerper == "Kugel":
        pi = 3.14159
        r = x/2 #  r ... Radius, x ... Durchmesser
        return koerper,  (4/3) * pi * (r**3)
    else:
        return f"unbekannt: {koerper}", None

Stern in def volumen(x, *, y=None, ...: Bis da hin müssen alle Pos-Parameter angegeben sein.

# z.B. Murmel mit ca 1.25 cm Durchmesser hat Volumen etwa 1 Kubikzentimeter
volumen(1.25, koerper="Kugel")
('Kugel', 1.0226529947916665)
# Positionsargumente + keyword argument
volumen_quader(a, b, c, koerper="Quader")
Meine Parameter: 
          x=0.5, y=1, z=2, 
          koerper='Quader'
('Quader', 1.0)
# Quader mit zu wenigen Werten wirft Fehler
#volumen_quader(a, koerper="Quader")

Stern-Operator#

Was ist, wenn wir die Werte in einem Dict haben?

meine_Kugel = { "koerper": "Kugel", "x": 1.25 }
meine_Kugel["x"], meine_Kugel["koerper"]
(1.25, 'Kugel')
# zu Fuß, korrekt, aber aufwändig
volumen( meine_Kugel["x"], koerper=meine_Kugel["koerper"] )
('Kugel', 1.0226529947916665)
# besser mit Stern-Operator:
# Dict und Parameter der Funktion werden zugeordnet,
# (Reihenfolge spielt keine Rolle)
volumen(**meine_Kugel)
('Kugel', 1.0226529947916665)
mein_Quader = { "koerper": "Quader", "x": 0.5, "y": 1, "z": 2 }
volumen(**mein_Quader)
('Quader', 1.0)

Wir haben im Folgenden ein Dict von Teilen:

  • Teil-ID

  • Teile-Beschreibung als Dict

#Teile = { 1: meine_Kugel, 2: mein_Quader }
Teile = { 1: { "koerper": "Kugel", "x": 1.25 } , 
          2: { "koerper": "Quader", "x": 0.5, "y": 1, "z": 2 }  }
# Volumen unserer Teile
for Beschreibung in Teile.values():
    print( f"""{Beschreibung=}, {volumen(**Beschreibung)=}""" )
    #print( volumen(**Beschreibung) )
Beschreibung={'koerper': 'Kugel', 'x': 1.25}, volumen(**Beschreibung)=('Kugel', 1.0226529947916665)
Beschreibung={'koerper': 'Quader', 'x': 0.5, 'y': 1, 'z': 2}, volumen(**Beschreibung)=('Quader', 1.0)
# das Volumen der Teile-Beschreibung hinzufügen
for Teile_ID, Beschreibung in Teile.items():
    vol = volumen(**Beschreibung)[1]
    Teile[Teile_ID]["vol"] = vol

Teile
{1: {'koerper': 'Kugel', 'x': 1.25, 'vol': 1.0226529947916665},
 2: {'koerper': 'Quader', 'x': 0.5, 'y': 1, 'z': 2, 'vol': 1.0}}

Variable Anzahl an Parametern#

TBD: *x, **x

Unterscheide: Sternchen (egal ob einfach oder doppelt)

  • im Funktionsaufruf

  • in der Funktions-Definition

Quelle z.B. https://www.python-kurs.eu/parameter.php > “Variable Anzahl von Parametern”

def beliebig(x, *Spiderman, **Superman):
    print(x)
    print(Spiderman)
    print(Superman)
beliebig("Das", "ist", "die", [ "Zahl", "Pi" ], 3.145, rettet="die Welt")
Das
('ist', 'die', ['Zahl', 'Pi'], 3.145)
{'rettet': 'die Welt'}

Mutable Objekte als Parameter?#

formate = { "A4": (210, 297),
            "C4": (324, 229),
            "B4": (250, 353) }

Funktion liefert Ergebnis zurück:

def flaeche(x, y):
    return x * y
qmm = []  # Quadradmillimeter
for (l, b) in formate.values():
    f = flaeche(l, b)
    qmm.append(f)
qmm
[62370, 74196, 88250]

oder als List Comprehension:

qmm = [ flaeche(l, b) for (l,b) in formate.values() ]
qmm
[62370, 74196, 88250]

Funktion verändert “mutable” Datenstruktur, hier ergebnisliste:

def flaeche2(x, y, ergebnisliste):
    ergebnisliste.append( x*y )
    return "böser Nebeneffekt"
qmm2 = []
for (l, b) in formate.values():
    f = flaeche2(l,b, qmm2)
    print( f )
qmm2
böser Nebeneffekt
böser Nebeneffekt
böser Nebeneffekt
[62370, 74196, 88250]

oder als sehr schmutzinge List Comprehension:

qmm2 = []

wegwerf = [ flaeche2(l, b, qmm2) for (l,b) in formate.values() ]
wegwerf
['böser Nebeneffekt', 'böser Nebeneffekt', 'böser Nebeneffekt']
qmm
[62370, 74196, 88250]

oder ein Dict als Ergebnisstruktur, mit Nebeneffekt (hässlich):

def flaeche2(pf, x, y, ergebnisdict):
    ergebnisdict[pf] = x*y
    return "böser Nebeneffekt"
qmm2 = {}

for papierformat, (l, b) in formate.items():
    f = flaeche2(papierformat, l,b, qmm2)
    #print( f )
qmm2
{'A4': 62370, 'C4': 74196, 'B4': 88250}