Funktionen

Die klassische Art ( modulares Programmieren) ein großes, komplexes Programm überschaubar zu gestalten ist die Aufteilung der Funktionalität in kleinere, eigenständige Untereinheiten für bestimmte Aufgaben, d.h. Einteilung in Funktionen.


def GravForce( mass1, mass2, distance): # Kopf der Funktion
    GRAV_CONST = 6.673e-11  # Gravitationskonstante  m^3 / ( kg s^2 )
    f = GRAV_CONST * mass1 * mass2 / distance**2 # Kraft ausrechnen
    return(f)                           # Ergebnis zurueckgeben

mSonne = 1.9889e30; mErde = 5.974e24; dErdeSonne = 1.49597e11; rErde = 6.378e6
# Aufruf von Funktion GravForce 
gErdeSonne = GravForce( mSonne, mErde, dErdeSonne ) # Kraft Sonne--Erde
print (gErdeSonne)
gPerson = GravForce( mErde, 80., rErde )            # Gewichtskraft 80 kg auf Erde
print (gPerson)


1-4
Definition der Funktion GravForce.
Zeile 1
Deklaration der Funktion GravForce:
Angabe von Namen der Funktion sowie Namen der Parameter.

Funktionsaufruf bewirkt
:

Image funccall

Programm–Design


Funktionen brauchen nicht immer Argumente ...

time.ctime() # returns current date and time
'Fri Mar 18 14:06:00 2005'

Funktionen müssen nicht unbedingt was zurückgeben


def greeting(): # Begruessung
    hour=time.localtime()[3] # extract Stunde
    gruss='Guten Tag'
    if (4<hour<10):
        gruss='Guten Morgen'
    elif  ( 11<hour<13 ):
        gruss='Mahlzeit'
    elif  ( 18<hour<21 ):
        gruss='Guten Abend'
    elif  (hour>21 or hour < 4):
        gruss='Gute Nacht'
#
    print(gruss)

Funktionen können mehrere Werte zurückgeben

(... nicht möglich in Java, FORTRAN, C/C++)


import math
def root( A, B, C):
    """ Returns the two roots of
      the quadratic equation A*x*x + B*x + C = 0."""
    disc = B*B - 4*A*C
    return (  (-B - math.sqrt(disc)) / (2*A),  (-B + math.sqrt(disc)) / (2*A) )
#

x1,x2 = root( 1., 5., -3.)  # return both solutions


Rekursive Funktionsaufrufe (Funktion ruft sich selbst) sind möglich:


def power( x, n ): # define power function 
    if ( n > 1 ) :
        return( x * power(x, n-1) ) # rekursiver Aufruf
    else:
        return( x )
#


power( x, 4 )

Image recursiveStack


Default Werte für Parameter

Keyword Argumente

Normalerweise wird beim Aufruf nur die Liste der Argumente übergeben und die Zuordnung der Argumente zu den Funktionsparametern geht nach der Position,
d.h. 1. Par = 1. Arg, 2. Par = 2. Arg, ....

Alternativ kann man beim Aufruf explizit den Namen (=keyword) einzelner Parameter angeben zusammen mit dem Argument: par-name=arg-wert


def parabel( x, a=0., b=0., c=0. ): # define parabel (poly 2)
    return( x**2 * a + x * b + c )
#
>>> parabel(2, 1., 2., 3.)
11.0
>>> parabel(2)  # default Werte fuer a,b,c
0.0
>>> parabel(2, 1.) # a=1, default Werte fuer b,c
4.0
>>> parabel(2, c=3)  # keyword-argument c=3, default Werte fuer a,b
3.0
>>> parabel(2, b=2)  # keyword-argument b=2, default Werte fuer a,c
4.0
>>> parabel(2, c=0, b=5)   # keyword-argument c,b, default Wert fuer a
10.0
>>> parabel()
#Traceback (most recent call last):
#  File "<stdin>", line 1, in ?
#TypeError: parabel() takes at least 1 argument (0 given)


lambda Funktionen

Anonyme Kurzform für Funktionen. Sie werden nicht mit def function-name ... deklariert wie bei den üblichen Funktionen, sondern quasi anonym in einer Zeile:


def squareAdd( x, y):
    return( x**2 + y**2)
#
f = lambda x, y : x**2 + y**2  # definition als lambda function in einer Zeile
#
# Aufruf
squareAdd( 2., 3. ) # = 13
#
f( 2., 3.) # aequivalent = 13

lambda functions sind vor allem dann nützlich wenn als Argument beim Aufruf einer Funktion eine Funktion benötigt wird. Sehr häufig bei GUI Funktionen: Verknüpfung von Ereignis (z.B. Mausklick) und Aktion ( call-back function). \bgroup\color{dblue}\ensuremath{\color{dgreen}{\Rightarrow}}\egroup Später

Weiteres Beispiel: Numerik – Nullstellen von Funktion


def suche( x1, x2, f ) :
    " suche Nullstelle von Funktion f zwischen x1 und x2"
    f1 = f(x1);
    f2 = f(x2);
    i = 0
    while  i < 1000  : #  Abbruch nach 1000 Iterationen
        xn = (x1+x2)/2.   # Neues x in Mitte
        fn = f(xn);       # Funktionswert dazu
        if  abs(fn) < 1e-6 : break # Konvergenz: 1e-6 an Nullstelle, dann Abbruch

        if  fn*f2 > 0.  :  # gleiches Vorzeichen wir f2 ?
            x2,f2 = xn,fn    #  dann ersetze x2,f2
        else:
            x1,f1 = xn,fn    # andernfalls x1,f1
            
        i = i+1
    else:                    # keine Konvergenz
        print 'Error: Keine Konvergenz fuer Nullstellensuche', fn
        
    return xn 
#
# Test
def myf(x) :
    return( math.exp(-x) -x);
#
print (suche( 0., 3., math.cos))  # Uebergebe Funktion aus math
print (suche( 0., 3., myf))       # Uebergebe selbst-definierte  Funktion 
print (suche( 0., 3., lambda x : math.exp(x) -2. )) # Ueber lambda func