Skip to content

6. Funktionen

Image

6.1. Skript [fonc_01]: Gültigkeitsbereich von Variablen

Das Skript [fonc_01] zeigt Beispiele für den Gültigkeitsbereich von Variablen zwischen Funktionen:

#  variable scope
def f1():
    #  avoid using global variables
    #  global variable i
    global i
    i += 1
    #  local variable j
    j = 10
    print(f"f1[i,j]=[{i},{j}]")


def f2():
    #  avoid using global variables
    #  global variable i
    global i
    i += 1
    #  local variable j
    j = 20
    print(f"f2[i,j]=[{i},{j}]")


def f3():
    #  local variable i
    i = 1
    #  local variable j
    j = 30
    print(f"f3[i,j]=[{i},{j}]")


#  main program
i = 0
j = 0
#  these two variables will only be known by a function f
#  only if it explicitly declares in the global instruction that it wants to use them
#  or that the function uses the global variable for reading only
f1()
f2()
f3()
#  j hasn't changed but i has
print(f"[i,j]=[{i},{j}]")

Ergebnisse


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_01.py
f1[i,j]=[1,10]
f2[i,j]=[2,20]
f3[i,j]=[1,30]
[i,j]=[2,0]
 
Process finished with exit code 0

Anmerkungen:

  • Das Skript veranschaulicht die Verwendung der Variablen i, die in den Funktionen f1 und f2 als global deklariert wurde. In diesem Fall teilen sich das Hauptprogramm und die Funktionen f1 und f2 dieselbe Variable i.

6.2. Skript [fonc_02]: Geltungsbereich von Variablen

Das Skript [fonc_03] baut auf dem Skript [fonc_02] auf und zeigt, wie die Verwendung globaler Variablen vermieden werden kann:

#  variable scope
def f1(i):
    #  local variable i
    i += 1
    #  local variable j
    j = 10
    print(f"f1[i,j]=[{i},{j}]")
    #  return the modified value
    return i


def f2(i):
    #  local variable i
    i += 1
    #  local variable j
    j = 20
    print(f"f2[i,j]=[{i},{j}]")
    #  return the modified value
    return i


def f3():
    #  local variable i
    i = 1
    #  local variable j
    j = 30
    print(f"f3[i,j]=[{i},{j}]")


#  main program
i = 0
j = 0
#  these two variables will only be known by a function f
#  only if it explicitly declares in the global instruction that it wants to use them
#  or if the function uses the global variable for reading only
i = f1(i)
i = f2(i)
f3()
#  j hasn't changed but i has
print(f"[i,j]=[{i},{j}]")

Kommentare:

  • Zeilen 2, 12: Anstatt global deklariert zu werden, wird die Variable [i] als Parameter an die Funktionen f1 und f2 übergeben;
  • Zeilen 9, 19: Die Funktionen f1 und f2 geben die geänderte Variable [i] an das Hauptprogramm zurück. Das Hauptprogramm ruft sie in den Zeilen 36 und 37 ab;

Ergebnisse


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_02.py
f1[i,j]=[1,10]
f2[i,j]=[2,20]
f3[i,j]=[1,30]
[i,j]=[2,0]
 
Process finished with exit code 0

6.3. Skript [fonc_03]: Geltungsbereich von Variablen

Das Skript [fonc_03] veranschaulicht eine Besonderheit von Variablen, die sowohl innerhalb einer Funktion als auch im aufrufenden Code verwendet werden, je nachdem, ob die Variable innerhalb der Funktion nur zum Lesen verwendet wird oder nicht.

def f1():
    #  here the global variable i is known
    print(f"[f1] i={i}")
    #  here the global variable j is known
    print(f"[f1] j={j}")


def f2():
    #  here the global variable i is not known
    #  because the f2 function defines a local variable with the same name
    #  it then has priority
    try:
        #  try displaying the local variable i defined below
        print(f"[f2] i={i}")
        #  the following instruction makes i a local variable of function f2
        i = 7
    except BaseException as erreur:
        print(f"[f2] erreur={erreur}")


def f3():
    #  here the global variable i is not known
    #  because the f3 function defines a local variable with the same name
    #  it then has priority

    #  the following instruction makes i a local variable
    i = 7
    #  display - here i is known
    print(f"[f3] i={i}")


#  hand -----------
#  global variables to functions
i = 10
j = 20
#  call from f1
f1()
print(f"[main] i={i}, j={j}")
#  call from f2
f2()
print(f"[main] i={i}")
#  call from f3
f3()
print(f"[main] i={i}")

Anmerkungen

  • Zeile 34: Der Hauptcode definiert eine Variable [i];
  • Zeilen 1–5: Die Funktion f1 verwendet ebenfalls eine Variable [i], ohne ihr einen Wert zuzuweisen. Hierbei handelt es sich um ein Auslesen der Variablen [i]. In diesem Fall wird die Variable [i] aus dem aufrufenden Code (Zeile 34) verwendet;
  • Zeilen 8–18: Die Funktion f2 verwendet ebenfalls eine Variable [i], weist ihr jedoch in Zeile 16 einen Wert zu. Durch die Zuweisung eines Werts an die Variable [i] in f2 wird [i] automatisch zu einer lokalen Variablen der Funktion [f2]. Diese Funktion „verbirgt“ daher die Variable [i] vor dem aufrufenden Code;
  • Zeile 14: Der Schreibvorgang auf die lokale Variable [i] schlägt fehl, da sie keinen Wert hat, wenn Zeile 14 erreicht wird. Sie erhält ihren Wert in Zeile 16. Es tritt eine Ausnahme auf. Aus diesem Grund wurde Zeile 14 in einen try/catch-Block gesetzt;
  • Zeilen 21–29: Die Funktion f3 macht dasselbe wie die Funktion f2, definiert ihre lokale Variable [i] jedoch früher;

Ergebnisse


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_03.py
[f1] i=10
[f1] j=20
[main] i=10, j=20
[f2] erreur=local variable 'i' referenced before assignment
[main] i=10
[f3] i=7
[main] i=10
 
Process finished with exit code 0

6.4. Skript [fonc_04]: Modus der Parameterübergabe

Das Skript lautet wie folgt:

#  function f1
def f1(a):
    a = 2


#  function f2
def f2(a, b):
    a = 2
    b = 3
    return a, b


#  ------------------------ hand
x = 1
f1(x)
print(f"x={x}")
(x, y) = (-1, -1)
(x, y) = f2(x, y)
print(f"x={x}, y={y}")

Ergebnisse

1
2
3
4
5
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_04.py
x=1
x=2, y=3

Process finished with exit code 0

Anmerkungen:

  • In Python ist alles ein Objekt. Manche Objekte werden als „unveränderlich“ bezeichnet: Sie können nicht verändert werden. Dies gilt für Zahlen, Zeichenketten und Tupel. Wenn Python-Objekte als Argumente an Funktionen übergeben werden, werden ihre Referenzen übergeben, es sei denn, diese Objekte sind „unveränderlich“; in diesem Fall wird der Wert des Objekts übergeben;
  • Die Funktionen f1 (Zeile 2) und f2 (Zeile 7) sollen die Übergabe eines Ausgabeparameters veranschaulichen. Wir möchten, dass der tatsächliche Parameter einer Funktion durch die Funktion verändert wird;
  • Zeilen 2–3: Die Funktion f1 verändert ihren formalen Parameter a. Wir wollen wissen, ob auch der tatsächliche Parameter verändert wird;
  • Zeilen 14–15: Der tatsächliche Parameter ist x = 1. Zeile 2 der Ergebnisse zeigt, dass der tatsächliche Parameter nicht verändert wird. Somit sind der tatsächliche Parameter x und der formale Parameter a zwei verschiedene Objekte;
  • Zeilen 8–10: Die Funktion f2 modifiziert ihre formalen Parameter a und b und gibt sie als Ergebnisse zurück;
  • Zeilen 17–18: Die tatsächlichen Parameter (x, y) werden an f2 übergeben, und das Ergebnis von f2 wird (x, y) zugewiesen. Zeile 3 der Ergebnisse zeigt, dass die tatsächlichen Parameter (x, y) geändert wurden.

Wir schließen daraus, dass „unveränderliche“ Objekte, wenn sie Ausgabeparameter sind, Teil der von der Funktion zurückgegebenen Ergebnisse sein müssen.

6.5. Skript [fonc_05]: Reihenfolge der Funktionen in einem Skript

Das Skript [fonc_05] zeigt, dass eine Funktion nicht aufgerufen werden kann, wenn sie zuvor im Code noch nicht aufgetreten ist:

#  ------------------------ hand
print(f2(100, 200))

#  function f1
def f1(a):
    return a + 10


#  function f2
def f2(a, b):
    return f1(a + b)

Anmerkungen

  • Zeile 2 führt zu einem Fehler, da sie die Funktion f2 verwendet, die im Skript noch nicht definiert wurde;

Ergebnisse

1
2
3
4
5
6
7
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_05.py
Traceback (most recent call last):
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_05.py", line 2, in <module>
    print(f2(100, 200))
NameError: name 'f2' is not defined

Process finished with exit code 1

6.6. Skript [fonc_06]: Reihenfolge der Funktionen in einem Skript

Das Skript [fonc_06] zeigt, dass das, was für den aufrufenden Code gilt, nicht für Funktionen gilt:

#  function f2
def f2(a, b):
    return f1(a + b)


#  function f1
def f1(a):
    return a + 10


#  ------------------------ hand
print(f2(100, 200))

Anmerkungen

  • Zeile 3: Die Funktion [f2] verwendet die später im Skript definierte Funktion [f1]. Dies führt jedoch nicht zu einem Fehler. Wir können daher schlussfolgern, dass die Reihenfolge, in der Funktionen in einem Python-Skript definiert werden, keine Rolle spielt;

Ergebnisse

1
2
3
4
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_06.py
310

Process finished with exit code 0

6.7. Skript [fonc_07]: Verwendung von Modulen

Das Skript [fonc_07] zeigt, wie Funktionen in einem Modul isoliert werden.

Image

Wir isolieren wiederverwendbare Funktionen in einem Modul, anstatt sie von einem Skript in ein anderes zu verschieben:

  • legen wir sie in einer separaten Datei ab, die wir auf eine bestimmte Weise deklarieren;
  • Skripte, die diese Funktionen benötigen, „importieren“ das Modul, das sie enthält;

Das Skript [fonctions_module_01] sieht wie folgt aus:

1
2
3
4
5
6
7
#  function f2
def f2(a, b):
    return f1(a + b)

#  function f1
def f1(a):
    return a + 10

Es gibt mehrere Möglichkeiten, um sicherzustellen, dass die Funktionen im Skript [fonctions_module_01] von anderen Skripten aufgerufen werden können. Diese Methoden unterscheiden sich je nachdem, ob das Skript innerhalb von [PyCharm] ausgeführt wird oder nicht.

In [PyCharm] wird in bestimmten Ordnern, den sogenannten [Root Sources], nach importierten Modulen gesucht. Es gibt zwei Möglichkeiten, einen Ordner als [Root Source] festzulegen:

Image

  • in [4] hat der Ordner seine Farbe geändert;

Nach diesem Vorgang wird der Ordner [functions/modules] als Quellordner erkannt. Sie können dann in einem Skript schreiben:

from fonctions_module_01 import f2

Um die im Modul [functions_module_01.py] definierte Funktion f2 zu importieren/zu verwenden.

Eine weitere Möglichkeit ist die Verwendung der Projekteigenschaften:

  • Oben ermöglicht die Sequenz [1-6], den Ordner [shared] als Speicherort für zu importierende Module zu verwenden;

Vorerst werden wir keinen anderen Ordner als [Sources Root] als das Projektverzeichnis angeben:

Image

Sobald dies erledigt ist, können wir das folgende Skript [fonc-07] schreiben:

1
2
3
4
5
6
7
8
#  using modules
import sys

#  ------------------------ hand
print(f"Python path={sys.path}")
from fonctions.shared.fonctions_module_01 import f2

print(f2(100, 200))
  • Zeile 2: Wir importieren das [sys]-Objekt, damit wir in Zeile 5 dessen [path]-Attribut verwenden können, das den sogenannten [Python Path] bereitstellt: eine Liste von Verzeichnissen, in denen nach importierten Modulen gesucht wird;
  • Zeile 6: Wir importieren die Funktion f2 aus dem Modul [fonctions_module_01]. Um auf dieses Modul zu verweisen, verwenden wir den Pfad, der vom Projektstammverzeichnis zum Modul führt. Bei PyCharm ist das Projektstammverzeichnis immer in den Ordnern enthalten, die durchsucht werden, wenn in einem Skript nach einem importierten Modul gesucht wird. Dieser Ordner ist daher Teil des [Python Path] des Projekts. Dies können wir anhand von Zeile 5 überprüfen;
  • Zeile 6: Würden wir den Pfad vom Projektstammverzeichnis zum Ordner [fonctions_module_01] beschreiben, würden wir [fonctions/shared/fonctions_module_01] schreiben. Im Pfad eines Moduls wird das / durch einen Punkt ersetzt. Wir schreiben daher [fonctions.modules.fonctions_module_01];
  • Nach Zeile 6 wird die Funktion f2 definiert. Wir verwenden sie in Zeile 8;

Ergebnisse


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_07.py
Python path=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions\\shared', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages']
310
 
Process finished with exit code 0

Oben:

  • grün hervorgehoben, sehen wir, dass das Projektverzeichnis Teil des [Python Path] ist;
  • gelb hervorgehoben ist, sehen wir, dass der Ordner, der das ausgeführte Skript enthält, ebenfalls Teil des [Python-Pfads] ist;
  • die anderen Elemente des [Python-Pfads] stammen direkt aus dem Python-Installationsordner;

Was passiert, wenn wir [fonc-07] nicht mit PyCharm ausführen?

Image

Image

  • In [1] führen wir das Skript [fonc-07] aus. Wir befinden uns im Ordner [functions];
  • In [2] sehen wir, dass das Ausführungsverzeichnis Teil des [Python Path] ist. Dies ist immer der Fall. Wir sehen auch, dass das Stammverzeichnis [C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020] nicht Teil des [Python Path] ist;
  • In [3] meldet der Python-Interpreter, dass er das Modul [fonctions] nicht finden kann;

Um das importierte Modul [fonctions.shared.fonctions_module_01] zu finden, durchsucht der Python-Interpreter die Ordner im [Python Path] nach einem Unterordner namens [fonctions]. Er kann ihn nirgendwo finden. Dies liegt daran, dass sich der Unterordner [fonctions] unter dem Ordner [C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020] befindet, der nicht Teil des [Python-Pfads] ist.

Das Skript [fonc-08] bietet eine mögliche Lösung für dieses Problem.

6.8. Skript [fonc_08]: Hinzufügen von Ordnern zum [Python Path]

Es ist möglich, den [Python-Pfad] programmgesteuert zu ändern, wie im Skript [fonc-08] gezeigt:

#  using modules
import os
import sys

#  script folder
script_dir = os.path.dirname(os.path.abspath(__file__))
#  Python Path before modification
print(f"Python path avant={sys.path}")
#  add the [shared] folder to the Python Path
sys.path.append(f"{script_dir}/shared")
#  Python Path after modification
print(f"Python path après={sys.path}")

#  import f2
from fonctions_module_01 import f2

#  ------------------------ hand
print(f2(100, 200))

Anmerkungen

  • Zeile 4: Die Spezialvariable [__file__] ist der Name des Skripts, das gerade ausgeführt wird. Je nach Ausführungskontext kann dieser Name absolut (PyCharm) oder relativ (Konsole) sein. Die Funktion [os.path.abspath] gibt den absoluten Pfad der Datei zurück, deren Name ihr übergeben wird. Die Funktion [os.path.dirname] gibt den absoluten Pfad des Verzeichnisses zurück, das die Datei enthält, deren Name ihr übergeben wird;
  • Zeile 10: [sys.path] ist eine Liste, die die Namen der Verzeichnisse enthält, in denen gesucht wird, wenn ein Modul gesucht wird. Wir fügen das in Zeile 4 definierte Projektstammverzeichnis zu dieser Liste hinzu;
  • Wir zeigen den [Python-Pfad] vor (Zeile 8) und nach (Zeile 12) der Änderung an;
  • Zeile 15: Wir importieren das Modul [fonctions_module_01], das die Funktion f2 enthält;

Die Ausführung in PyCharm liefert folgende Ergebnisse:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_08.py
Python path avant=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions\\shared', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages']
Python path après=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions\\shared', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions/shared']
310
 
Process finished with exit code 0
  • Zeile 3: Wir sehen, dass der Ordner [shared] zweimal im [Python Path] erscheint. Wir können dies vermeiden, aber es verursacht hier keine Probleme;
  • Zeile 4: Die Funktion f2 wurde erfolgreich ausgeführt;

Führen wir nun [fonc-08] in einem Terminal aus:


(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions>python fonc_08.py
Python path avant=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages']
Python path après=['C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions', 'C:\\myprograms\\Python38\\python38.zip', 'C:\\myprograms\\Python38\\DLLs', 'C:\\myprograms\\Python38\\lib', 'C:\\myprograms\\Python38', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\venv\\lib\\site-packages', 'C:\\Data\\st-2020\\dev\\python\\cours-2020\\python3-flask-2020\\fonctions/shared']
310
  • Zeile 2: Wie zuvor befindet sich der Ordner [shared] nicht im [Python-Pfad];
  • Zeile 3: Jetzt ist er es;
  • Zeile 4: Die Funktion f2 wurde gefunden;

6.9. Skript [fonc_09]: Deklaration von Parametertypen

Das Skript [fonc_09] zeigt, dass Sie sowohl den Typ der Parameter einer Funktion als auch den des Ergebnisses deklarieren können. Diese Deklaration dient jedoch lediglich der Dokumentation der Funktion. Der Python-Interpreter prüft nicht, ob die tatsächlichen Funktionsparameter vom erwarteten Typ sind. PyCharm markiert jedoch Typinkonsistenzen zwischen tatsächlichen und formalen Parametern. Allein aus diesem Grund sind Typdeklarationen unverzichtbar.

Das Skript lautet wie folgt:

#  a function with parameter type indication
#  this is for documentation purposes only, as the python interpreter ignores it


def show(param: int) -> int:
    print(f"param={param}, type(param)={type(param)}")
    return param + 1


#  hand -------------------------
print(show(4))
show("xyz")

Anmerkungen:

  • Zeile 5: Wir deklarieren, dass der formale Parameter [param] vom Typ [int] ist und dass der Rückgabetyp der Funktion ebenfalls [int] ist;
  • Zeile 11: Der tatsächliche Parameter der Funktion [show] hat den richtigen Typ;
  • Zeile 12: Der tatsächliche Parameter der Funktion [show] hat nicht den richtigen Typ;

Ergebnisse

C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_09.py
param=4, type(param)=<class 'int'>
5
param=xyz, type(param)=<class 'str'>
Traceback (most recent call last):
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_09.py", line 11, in <module>
    show("xyz")
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_09.py", line 6, in show
    return param + 1
TypeError: can only concatenate str (not "int") to str

Process finished with exit code 1
  • Zeile 10: Der Typ des Parameters [param] ist [str]. Wenn diese Meldung erscheint, haben wir bereits den Code der Funktion [show] eingegeben. Der Python-Interpreter hat daher akzeptiert, dass der tatsächliche Parameter der Funktion [show] vom Typ [str] ist;
  • Zeile 7 des Codes löst die in den Zeilen 4–10 der Ergebnisse gezeigte Ausnahme aus;

PyCharm weist dennoch darauf hin, dass ein Problem vorliegt:

Image

In [1] hat PyCharm den fehlerhaften Aufruf hervorgehoben.

6.10. Skript [fonc_10]: benannte Parameter

Um Parameter an eine Funktion zu übergeben, können Sie die Namen ihrer formalen Parameter verwenden. In diesem Fall müssen Sie die Reihenfolge der formalen Parameter nicht einhalten:

1
2
3
4
5
6
7
#  we can refer to the actual parameters by their formal names
def f(x, y):
    return x + y


#  hand
print(f(y=10, x=3))

Anmerkungen

  • Zeile 2: Die Funktion f hat zwei formale Parameter, x und y;
  • Zeile 7: Beim Aufruf der Funktion f können Sie die Namen der formalen Parameter verwenden. Diese Vorgehensweise kann in mindestens zwei Fällen nützlich sein:
    • Die Funktion hat viele Parameter, von denen die meisten Standardwerte haben. Beim Aufruf der Funktion ermöglicht die oben beschriebene Technik, nur jene Parameter zu initialisieren, für die Sie den Standardwert nicht verwenden möchten;
    • Wenn die formalen Parameter aussagekräftige Namen haben, verbessert die Verwendung benannter Parameter im Funktionsaufruf die Lesbarkeit des Codes;

Ergebnisse

1
2
3
4
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_10.py
13

Process finished with exit code 0

6.11. Skript [fonc_11]: rekursive Funktion

Das Skript [fonc_11] ist ein Beispiel für eine rekursive Funktion (die sich selbst aufruft):

#  recursive function
def fact(i: int) -> int:
    #  factorial(1) is 1
    #  a recursive function must terminate at a certain point
    if i == 1:
        return 1
    else:
        #  factorial(i)=i*factorial(i-1)
        return i * fact(i - 1)


#  ---------- hand
print(f"fact(8)={fact(8)}")

Kommentare

  • Zeilen 1–9: die Fakultätsfunktion;
  • Zeile 9: Die [Fakultäts-]Funktion ruft sich selbst auf;
  • Zeilen 5–6: Eine rekursive Funktion muss immer aufhören, wenn eine Bedingung erfüllt ist; andernfalls kommt es zu einer unendlichen Rekursion;

Ergebnisse

1
2
3
4
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_11.py
fact(8)=40320

Process finished with exit code 0

6.12. Skript [fonc_12]: rekursive Funktion

Die Funktion [fonc_12] liefert weitere Details zur Funktionsweise der Rekursion:

#  recursive function
#  behavior of parameter j


def fact(i: int, j: int) -> int:
    #  stop recursive function
    if i == 1:
        print(f"j={j}")
        return 1
    else:
        #  we manipulate j
        j += 1
        print(f"avant fact j={j}")
        #  recursivity
        f = fact(i - 1, j)
        print(f"après fact j={j}")
        #  result
        return i * f


#  ---------- hand
print(f"fact(8)={fact(8, 0)}")

Kommentare

  • Zeile 5: Wir konzentrieren uns weiterhin auf die Fakultätsfunktion. Wir fügen ihr den Parameter [j] hinzu;
  • Zeile 12: Die Variable j wird bei jeder Fakultätsberechnung regelmäßig erhöht. Wir zeigen ihren Wert vor (Zeile 12) und nach (Zeile 16) der Rekursion (Zeile 15) an;

Ergebnisse

C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/fonctions/fonc_12.py
avant fact j=1
avant fact j=2
avant fact j=3
avant fact j=4
avant fact j=5
avant fact j=6
avant fact j=7
j=7
après fact j=7
après fact j=6
après fact j=5
après fact j=4
après fact j=3
après fact j=2
après fact j=1
fact(8)=40320

Process finished with exit code 0
  • Zeilen 2–8: Wir sehen, dass der Wert von [j] so lange ansteigt, wie die Rekursion andauert, bis die Bedingung erfüllt ist, bei der die Rekursion beendet wird. Ab diesem Zeitpunkt erfolgt die Rückgabe aus den Aufrufen der Funktion [fact] in umgekehrter Reihenfolge der Aufrufe;
  • Zeilen 10–16: Diese Anzeigen spiegeln die aufeinanderfolgenden Rückgaben aus dem Aufruf von factorial wider. Die Variable [j] kehrt zu ihrem Ausgangswert 1 zurück;