Suche…


Einführung

Funktionen in Python bieten organisierten, wiederverwendbaren und modularen Code zum Ausführen bestimmter Aktionen. Funktionen vereinfachen den Codierungsprozess, verhindern redundante Logik und erleichtern die Verfolgung des Codes. In diesem Thema wird die Deklaration und Verwendung von Funktionen in Python beschrieben.

Python hat viele integrierte Funktionen wie print() , input() und len() . Neben den integrierten Funktionen können Sie auch eigene Funktionen erstellen, um spezifischere Aufgaben auszuführen. Diese Funktionen werden als benutzerdefinierte Funktionen bezeichnet .

Syntax

  • def funktionsname ( arg1, ... argN, * args, kw1, kw2 = default, ..., ** kwargs ): Anweisungen
  • Lambda arg1, ... argN, * args, kw1, kw2 = default, ..., ** kwargs : Ausdruck

Parameter

Parameter Einzelheiten
arg1 , ..., argN Regelmäßige Argumente
* args Unbenannte Positionsargumente
kw1 , ..., kwN Nur ausschließliche Argumente
** Kwargs Der Rest der Schlüsselwortargumente

Bemerkungen

5 grundlegende Dinge, die Sie mit Funktionen machen können:

  • Weisen Sie den Variablen Funktionen zu

    def f():
      print(20)
    y = f
    y()
    # Output: 20
    
  • Funktionen innerhalb anderer Funktionen definieren ( verschachtelte Funktionen )

    def f(a, b, y):
        def inner_add(a, b):      # inner_add is hidden from outer code
            return a + b
        return inner_add(a, b)**y
    
  • Funktionen können andere Funktionen zurückgeben

    def f(y):
        def nth_power(x):
            return x ** y
        return nth_power    # returns a function
    
    squareOf = f(2)         # function that returns the square of a number           
    cubeOf = f(3)           # function that returns the cube of a number
    squareOf(3)             # Output: 9
    cubeOf(2)               # Output: 8
    
  • Funktionen können als Parameter an andere Funktionen übergeben werden

    def a(x, y):
        print(x, y)
    def b(fun, str):        # b has two arguments: a function and a string 
        fun('Hello', str)
    b(a, 'Sophia')           # Output: Hello Sophia
    
  • Innere Funktionen haben Zugriff auf den umschließenden Bereich ( Closure )

    def outer_fun(name):
        def inner_fun():     # the variable name is available to the inner function
            return "Hello "+ name + "!"
        return inner_fun
    greet = outer_fun("Sophia")
    print(greet())            # Output: Hello Sophia!
    

Zusätzliche Ressourcen

Einfache Funktionen definieren und aufrufen

Die def Anweisung ist die gebräuchlichste Methode zum Definieren einer Funktion in Python. Diese Anweisung ist eine sogenannte Einzelklausel-Verbundanweisung mit der folgenden Syntax:

def function_name(parameters):
    statement(s)

function_name ist als Bezeichner der Funktion bekannt. Da eine Funktionsdefinition eine ausführbare Anweisung ist, bindet ihre Ausführung den Funktionsnamen an das Funktionsobjekt, das später mit dem Bezeichner aufgerufen werden kann.

parameters ist eine optionale Liste von Bezeichnern, die beim Aufruf der Funktion an die als Argumente angegebenen Werte gebunden werden. Eine Funktion kann eine beliebige Anzahl von Argumenten haben, die durch Kommas getrennt sind.

statement(s) - auch Funktionskörper genannt - sind eine nicht leere Folge von Anweisungen, die bei jedem Aufruf der Funktion ausgeführt werden. Dies bedeutet, dass ein Funktionskörper nicht wie ein eingerückter Block leer sein darf.

Hier ist ein Beispiel für eine einfache Funktionsdefinition, die dazu dient, Hello jedem Aufruf zu drucken:

def greet():
    print("Hello")

Rufen wir nun die definierte Funktion greet() :

greet()
# Out: Hello

Dies ist ein weiteres Beispiel für eine Funktionsdefinition, die ein einzelnes Argument verwendet und bei jedem Aufruf der Funktion den übergebenen Wert anzeigt:

def greet_two(greeting):
    print(greeting)

Danach muss die Funktion greet_two() mit einem Argument aufgerufen werden:

greet_two("Howdy")
# Out: Howdy

Sie können diesem Funktionsargument auch einen Standardwert zuweisen:

def greet_two(greeting="Howdy"):
    print(greeting)

Jetzt können Sie die Funktion aufrufen, ohne einen Wert anzugeben:

greet_two()
# Out: Howdy 

Sie werden feststellen, dass Sie im Gegensatz zu vielen anderen Sprachen keinen Rückgabetyp der Funktion explizit angeben müssen. Python-Funktionen können über das Schlüsselwort return Werte eines beliebigen Typs return . Eine Funktion kann eine beliebige Anzahl verschiedener Typen zurückgeben!

def many_types(x):
    if x < 0:
        return "Hello!"
    else:
        return 0

print(many_types(1))
print(many_types(-1))

# Output:
0
Hello!

Solange dies vom Aufrufer korrekt gehandhabt wird, ist dies ein absolut gültiger Python-Code.

Eine Funktion, die das Ende der Ausführung ohne return-Anweisung erreicht, gibt immer None .

def do_nothing():
    pass

print(do_nothing())
# Out: None

Wie bereits erwähnt, muss eine Funktionsdefinition einen Funktionskörper haben, eine nicht leere Anweisungsfolge. Daher wird die pass Anweisung als Funktionshauptteil verwendet. Dies ist eine Nulloperation - wenn sie ausgeführt wird, passiert nichts. Es macht was es bedeutet, es überspringt. Es ist nützlich als Platzhalter, wenn eine Anweisung syntaktisch erforderlich ist, jedoch kein Code ausgeführt werden muss.

Werte von Funktionen zurückgeben

Funktionen können return einen Wert, den Sie direkt verwenden können:

def give_me_five():
    return 5

print(give_me_five())  # Print the returned value
# Out: 5

oder speichern Sie den Wert zur späteren Verwendung:

num = give_me_five()
print(num)             # Print the saved returned value
# Out: 5

oder verwenden Sie den Wert für alle Operationen:

print(give_me_five() + 10)
# Out: 15

Wenn in der Funktion " return auftritt, wird die Funktion sofort verlassen und nachfolgende Operationen werden nicht ausgewertet:

def give_me_another_five():
    return 5
    print('This statement will not be printed. Ever.')

print(give_me_another_five())
# Out: 5

Sie können auch return mehrere Werte (in Form eines Tupels):

def give_me_two_fives():
    return 5, 5  # Returns two 5

first, second = give_me_two_fives()
print(first)
# Out: 5
print(second)
# Out: 5

Eine Funktion ohne return Anweisung gibt implizit None . Ebenso wird eine Funktion mit einer return - Anweisung, aber kein Rückgabewert oder Variable kehrt None .

Funktion mit Argumenten definieren

Argumente werden in Klammern hinter dem Funktionsnamen definiert:

def divide(dividend, divisor):  # The names of the function and its arguments
    # The arguments are available by name in the body of the function
    print(dividend / divisor)

Der Funktionsname und seine Liste der Argumente werden als Signatur der Funktion bezeichnet. Jedes benannte Argument ist effektiv eine lokale Variable der Funktion.

Geben Sie beim Aufrufen der Funktion Werte für die Argumente an, indem Sie sie nacheinander auflisten

divide(10, 2)
# output: 5

oder spezifizieren Sie sie in beliebiger Reihenfolge anhand der Namen aus der Funktionsdefinition:

divide(divisor=2, dividend=10)
# output: 5

Definieren einer Funktion mit optionalen Argumenten

Optionale Argumente können definiert werden, indem dem Argumentnamen (mit = ) ein Standardwert zugewiesen wird:

def make(action='nothing'):
    return action

Der Aufruf dieser Funktion ist auf drei verschiedene Arten möglich:

make("fun")
# Out: fun

make(action="sleep")
# Out: sleep

# The argument is optional so the function will use the default value if the argument is 
# not passed in.
make()   
# Out: nothing

Warnung

Veränderbare Typen ( list , dict , set usw.) sollten sorgfältig behandelt werden, wenn sie als Standardattribut angegeben werden. Jede Änderung des Standardarguments ändert es dauerhaft. Siehe Definieren einer Funktion mit optionalen veränderbaren Argumenten .

Funktion mit mehreren Argumenten definieren

Man kann einer Funktion so viele Argumente geben, wie man möchte, die einzigen festen Regeln sind, dass jeder Argumentname eindeutig sein muss und dass optionale Argumente hinter den nicht-optionalen Argumenten stehen müssen:

def func(value1, value2, optionalvalue=10):
    return '{0} {1} {2}'.format(value1, value2, optionalvalue1)

Beim Aufruf der Funktion können Sie entweder jedes Schlüsselwort ohne Namen angeben, aber dann ist die Reihenfolge von Bedeutung:

print(func(1, 'a', 100))
# Out: 1 a 100

print(func('abc', 14))
# abc 14 10

Oder kombinieren Sie die Argumente mit Namen und außerhalb. Dann müssen diejenigen mit Namen denen ohne Namen folgen, aber die Reihenfolge der Namen mit Namen spielt keine Rolle:

print(func('This', optionalvalue='StackOverflow Documentation', value2='is'))
# Out: This is StackOverflow Documentation

Definieren einer Funktion mit einer beliebigen Anzahl von Argumenten

Beliebige Anzahl von Positionsargumenten:

Das Definieren einer Funktion, die eine beliebige Anzahl von Argumenten annehmen kann, kann durch Anfügen eines der Argumente mit einem *

def func(*args):
    # args will be a tuple containing all values that are passed in
    for i in args:
        print(i)

func(1, 2, 3)  # Calling it with 3 arguments
# Out: 1
#      2
#      3

list_of_arg_values = [1, 2, 3]
func(*list_of_arg_values)  # Calling it with list of values, * expands the list
# Out: 1
#      2
#      3 

func()  # Calling it without arguments
# No Output 

Sie können keine Standardwerte für args , z. B. führt func(*args=[1, 2, 3]) zu einem Syntaxfehler (wird nicht kompiliert).

Sie können diese nicht beim Namen TypeError , TypeError func(*args=[1, 2, 3]) einen TypeError .

Aber wenn Sie bereits Ihre Argumente in einem Array (oder jede andere Iterable :), können Sie Ihre Funktion wie folgt aufrufen func(*my_stuff) .

Auf diese Argumente ( *args ) kann über einen Index zugegriffen werden. Beispielsweise gibt args[0] das erste Argument zurück

Beliebige Anzahl von Schlüsselwortargumenten

Sie können eine beliebige Anzahl von Argumenten mit einem Namen verwenden, indem Sie ein Argument in der Definition mit zwei * :

def func(**kwargs):
    # kwargs will be a dictionary containing the names as keys and the values as values
    for name, value in kwargs.items():
        print(name, value)

func(value1=1, value2=2, value3=3)   # Calling it with 3 arguments
# Out: value1 1
#      value2 2
#      value3 3

func()                               # Calling it without arguments
# No Out put

my_dict = {'foo': 1, 'bar': 2}
func(**my_dict)                      # Calling it with a dictionary
# Out: foo 1
#      bar 2

Sie können diese Namen nicht ohne Namen TypeError , z. B. wird durch func(1, 2, 3) ein TypeError .

kwargs ist ein einfaches Python-Wörterbuch. Beispielsweise gibt args['value1'] den Wert für das Argument value1 . Vergewissern Sie sich vorher, dass ein solches Argument KeyError oder ein KeyError wird KeyError .

Warnung

Sie können diese mit anderen optionalen und erforderlichen Argumenten mischen, aber die Reihenfolge innerhalb der Definition ist wichtig.

Die positionellen / Keyword- Argumente stehen an erster Stelle. (Erforderliche Argumente).
Dann kommt die willkürlichen *arg Argumente. (Wahlweise).
Als Nächstes kommen nur ausschließliche Keyword- Argumente. (Erforderlich).
Schließlich kommt das beliebige Stichwort **kwargs . (Wahlweise).

#       |-positional-|-optional-|---keyword-only--|-optional-|
def func(arg1, arg2=10 , *args, kwarg1, kwarg2=2, **kwargs):
     pass
  • arg1 muss angegeben werden, andernfalls wird ein TypeError . Es kann als positionelles ( func(10) ) oder Schlüsselwortargument func(arg1=10) ) angegeben werden.
  • kwarg1 muss ebenfalls angegeben werden, es kann jedoch nur als Schlüsselwortargument angegeben werden: func(kwarg1=10) .
  • arg2 und kwarg2 sind optional. Wenn der Wert geändert werden soll, gelten die gleichen Regeln wie für arg1 (entweder positional oder Schlüsselwort) und kwarg1 (nur Schlüsselwort).
  • *args fängt zusätzliche Positionsparameter ab. Beachten Sie jedoch, dass arg1 und arg2 als Positionsargumente arg2 müssen, um Argumente an *args : func(1, 1, 1, 1) .
  • **kwargs alle zusätzlichen Schlüsselwortparameter. In diesem Fall ein Parameter, der nicht arg1 , arg2 , kwarg1 oder kwarg2 . Zum Beispiel: func(kwarg3=10) .
  • In Python 3 können Sie mit * allein angeben, dass alle nachfolgenden Argumente als Schlüsselwörter angegeben werden müssen. Zum Beispiel wird die math.isclose Funktion in Python 3.5 und höher mit def math.isclose (a, b, *, rel_tol=1e-09, abs_tol=0.0) definiert def math.isclose (a, b, *, rel_tol=1e-09, abs_tol=0.0) , was bedeutet, dass die ersten beiden Argumente positionell angegeben werden können, die optionalen jedoch Der dritte und der vierte Parameter können nur als Schlüsselwortargumente angegeben werden.

Python 2.x unterstützt keine reinen Keyword-Parameter. Dieses Verhalten kann mit kwargs emuliert kwargs :

def func(arg1, arg2=10, **kwargs):
    try:
        kwarg1 = kwargs.pop("kwarg1")
    except KeyError:
        raise TypeError("missing required keyword-only argument: 'kwarg1'")

    kwarg2 = kwargs.pop("kwarg2", 2)
    # function body ...

Hinweis zum Benennen

Die Konvention der optionalen Positionsargumente Benennung args und optionale Schlüsselwort Argumente kwargs ist nur eine Konvention Sie keine Namen verwenden , die Sie mögen , aber es ist nützlich , um die Konvention zu folgen , damit andere wissen , was Sie tun, oder sich auch später so bitte tun.

Hinweis zur Einzigartigkeit

Jede Funktion kann mit keiner oder einer *args und keiner oder einer **kwargs jedoch nicht mit mehr als einer davon. *args muss auch das letzte Positionsargument sein und **kwargs muss der letzte Parameter sein. Wenn Sie versuchen, mehr als eine von beiden zu verwenden, führt dies zu einer Syntaxfehler-Ausnahme.

Hinweis zu Verschachtelungsfunktionen mit optionalen Argumenten

Es ist möglich, Nest solche Funktionen und die übliche Konvention ist es, die Elemente zu entfernen , dass der Code bereits behandelt hat , aber wenn Sie die Parameter durch die Über werden müssen Sie optionale Positions args mit einem passieren * Präfix und optionale Schlüsselwort args mit einem ** Präfix , andernfalls werden args with als Liste oder Tupel und kwargs als einzelnes Wörterbuch übergeben. z.B:

def fn(**kwargs):
    print(kwargs)
    f1(**kwargs)

def f1(**kwargs):
    print(len(kwargs))

fn(a=1, b=2)
# Out:
# {'a': 1, 'b': 2}
# 2

Definieren einer Funktion mit optionalen veränderbaren Argumenten

Es gibt ein Problem bei der Verwendung optionaler Argumente mit einem veränderbaren Standardtyp (beschrieben in Funktion mit optionalen Argumenten definieren ), die möglicherweise zu unerwartetem Verhalten führen.

Erläuterung

Dieses Problem tritt auf, weil die Standardargumente einer Funktion einmalig an dem Punkt initialisiert werden , an dem die Funktion definiert ist , und nicht (wie viele andere Sprachen), wenn die Funktion aufgerufen wird . Die Standardwerte werden in der __defaults__ des Funktionsobjekts gespeichert.

def f(a, b=42, c=[]):
    pass

print(f.__defaults__)
# Out: (42, [])

Für unveränderliche Typen (siehe Argumentübergabe und Mutabilität ) ist dies kein Problem, da die Variable nicht mutiert werden kann. es kann immer nur neu zugewiesen werden, wobei der ursprüngliche Wert unverändert bleibt. Daher ist garantiert, dass Folger den gleichen Standardwert hat. Bei einem veränderbaren Typ kann der ursprüngliche Wert jedoch geändert werden, indem die verschiedenen Memberfunktionen aufgerufen werden. Bei aufeinanderfolgenden Aufrufen der Funktion wird daher nicht garantiert, dass sie den ursprünglichen Standardwert haben.

def append(elem, to=[]):
    to.append(elem)      # This call to append() mutates the default variable "to"
    return to

append(1)
# Out: [1]

append(2)  # Appends it to the internally stored list
# Out: [1, 2]

append(3, [])  # Using a new created list gives the expected result
# Out: [3]

# Calling it again without argument will append to the internally stored list again
append(4)   
# Out: [1, 2, 4]

Hinweis: Einige IDEs wie PyCharm geben eine Warnung aus, wenn ein veränderlicher Typ als Standardattribut angegeben wird.

Lösung

Wenn Sie sicherstellen möchten, dass das Standardargument immer das von Ihnen in der Funktionsdefinition angegebene ist, verwenden Sie als Standardargument immer einen unveränderlichen Typ.

Um dies zu erreichen, wenn ein veränderlicher Typ als Standard benötigt wird, verwenden Sie None (unveränderlich) als Standardargument und weisen dann der Argumentvariablen den tatsächlichen Standardwert zu, wenn dieser mit None übereinstimmt.

def append(elem, to=None):
    if to is None:
        to = []

    to.append(elem)
    return to

Lambda (Inline / Anonym) Funktionen

Das Schlüsselwort lambda erstellt eine Inline-Funktion, die einen einzelnen Ausdruck enthält. Der Wert dieses Ausdrucks gibt die Funktion zurück, wenn sie aufgerufen wird.

Betrachten Sie die Funktion:

def greeting():
    return "Hello"

welche, wenn aufgerufen als:

print(greeting())

druckt:

Hello

Dies kann wie folgt als Lambda-Funktion geschrieben werden:

greet_me = lambda: "Hello"

Beachten Sie den Hinweis am Ende dieses Abschnitts bezüglich der Zuordnung von Lambdas zu Variablen. Tun Sie es im Allgemeinen nicht.

Dadurch wird eine Inline-Funktion mit dem Namen greet_me , die Hello zurückgibt. Beachten Sie, dass Sie beim Erstellen einer Funktion mit Lambda kein return schreiben. Der Wert nach : wird automatisch zurückgegeben.

Sobald eine Variable zugewiesen wurde, kann sie wie eine reguläre Funktion verwendet werden:

print(greet_me())

druckt:

Hello

lambda s kann auch Argumente annehmen:

strip_and_upper_case = lambda s: s.strip().upper()

strip_and_upper_case("  Hello   ")

gibt den String zurück:

HELLO

Sie können ebenso wie normale Funktionen eine beliebige Anzahl von Argumenten / Schlüsselwortargumenten annehmen.

greeting = lambda x, *args, **kwargs: print(x, args, kwargs)
greeting('hello', 'world', world='world')

druckt:

hello ('world',) {'world': 'world'}

lambda Werte werden üblicherweise für kurze Funktionen verwendet, die sich an dem Punkt definieren lassen, an dem sie aufgerufen werden (normalerweise mit sorted , filter und map ).

In dieser Zeile wird beispielsweise eine Liste von Zeichenfolgen sortiert, wobei der Groß- und Kleinschreibung am Anfang und am Ende ignoriert wird:

sorted( [" foo ", "    bAR", "BaZ    "], key=lambda s: s.strip().upper())
# Out:
# ['    bAR', 'BaZ    ', ' foo ']

Sortierliste, wobei Whitespaces ignoriert werden:

sorted( [" foo ", "    bAR", "BaZ    "], key=lambda s: s.strip())
# Out:
# ['BaZ    ', '    bAR', ' foo ']

Beispiele mit map :

sorted( map( lambda s: s.strip().upper(), [" foo ", "    bAR", "BaZ    "]))
# Out:
# ['BAR', 'BAZ', 'FOO']

sorted( map( lambda s: s.strip(), [" foo ", "    bAR", "BaZ    "]))
# Out:
# ['BaZ', 'bAR', 'foo']

Beispiele mit numerischen Listen:

my_list = [3, -4, -2, 5, 1, 7]
sorted( my_list, key=lambda x: abs(x))
# Out:
# [1, -2, 3, -4, 5, 7]

list( filter( lambda x: x>0, my_list))
# Out:
# [3, 5, 1, 7]

list( map( lambda x: abs(x), my_list))
# Out:
[3, 4, 2, 5, 1, 7]

Andere Funktionen (mit / ohne Argumente) können aus einer Lambda-Funktion heraus aufgerufen werden.

def foo(msg):
    print(msg)

greet = lambda x = "hello world": foo(x)
greet()

druckt:

hello world

Dies ist nützlich, da lambda möglicherweise nur einen Ausdruck enthält und durch die Verwendung einer untergeordneten Funktion mehrere Anweisungen ausgeführt werden können.


HINWEIS

Beachten Sie, dass PEP-8 (der offizielle Python-Styleguide) nicht empfiehlt, Variablen Lambdas zuzuweisen (wie in den ersten beiden Beispielen):

Verwenden Sie immer eine def-Anweisung anstelle einer Zuweisungsanweisung, die einen Lambda-Ausdruck direkt an einen Bezeichner bindet.

Ja:

def f(x): return 2*x

Nein:

f = lambda x: 2*x

Die erste Form bedeutet, dass der Name des resultierenden Funktionsobjekts spezifisch f anstelle des generischen <lambda> . Dies ist im Allgemeinen für Tracebacks und Stringdarstellungen sinnvoller. Die Verwendung der Zuweisungsanweisung eliminiert den einzigen Vorteil, den ein Lambda-Ausdruck gegenüber einer expliziten def Anweisung bieten kann (dh, er kann in einen größeren Ausdruck eingebettet werden).

Argumentübergabe und Veränderlichkeit

Zunächst einige Begriffe:

  • Argument ( Aktualparameter ): Die tatsächliche Variable, die an eine Funktion übergeben wird.
  • Parameter (formal parameter): der empfangende Variable, die in einer Funktion verwendet wird.

In Python werden Argumente per Zuweisung übergeben (im Gegensatz zu anderen Sprachen, in denen Argumente per Wert / Referenz / Zeiger übergeben werden können).

  • Durch die Mutation eines Parameters wird das Argument mutiert (wenn der Typ des Arguments variabel ist).

    def foo(x):        # here x is the parameter
        x[0] = 9       # This mutates the list labelled by both x and y
        print(x)
    
    y = [4, 5, 6]
    foo(y)             # call foo with y as argument
    # Out: [9, 5, 6]   # list labelled by x has been mutated
    print(y)           
    # Out: [9, 5, 6]   # list labelled by y has been mutated too
    
  • Durch die Neuzuweisung des Parameters wird das Argument nicht erneut zugewiesen.

    def foo(x):        # here x is the parameter, when we call foo(y) we assign y to x
        x[0] = 9       # This mutates the list labelled by both x and y
        x = [1, 2, 3]  # x is now labeling a different list (y is unaffected)
        x[2] = 8       # This mutates x's list, not y's list
      
    y = [4, 5, 6]      # y is the argument, x is the parameter
    foo(y)             # Pretend that we wrote "x = y", then go to line 1
    y
    # Out: [9, 5, 6]
    

In Python weisen wir Variablen keine Werte zu, stattdessen binden (dh Namen zuweisen) Variablen (als Namen betrachtet ) an Objekte.

  • Unveränderlich: Ganzzahlen, Strings, Tupel usw. Alle Operationen machen Kopien.
  • Veränderbar: Listen, Wörterbücher, Sets usw. Operationen können mutieren oder nicht.
x = [3, 1, 9]
y = x
x.append(5)    # Mutates the list labelled by x and y, both x and y are bound to [3, 1, 9]
x.sort()       # Mutates the list labelled by x and y (in-place sorting)
x = x + [4]    # Does not mutate the list (makes a copy for x only, not y)
z = x          # z is x ([1, 3, 9, 4])
x += [6]       # Mutates the list labelled by both x and z (uses the extend function).
x = sorted(x)  # Does not mutate the list (makes a copy for x only).
x
# Out: [1, 3, 4, 5, 6, 9]
y
# Out: [1, 3, 5, 9]
z
# Out: [1, 3, 5, 9, 4, 6]

Schließung

Schließungen in Python werden durch Funktionsaufrufe erstellt. Der Aufruf von makeInc erstellt hier eine Bindung für x , auf die in der Funktion inc verwiesen wird. Jeder Aufruf von makeInc erstellt eine neue Instanz dieser Funktion, aber jede Instanz hat einen Link zu einer anderen Bindung von x .

def makeInc(x):
  def inc(y):
     # x is "attached" in the definition of inc
     return y + x

  return inc

incOne = makeInc(1)
incFive = makeInc(5)

incOne(5) # returns 6
incFive(5) # returns 10

Beachten Sie, dass während eines regulären Abschlusses die eingeschlossene Funktion alle Variablen vollständig von ihrer umgebenden Umgebung erbt. In diesem Konstrukt hat die eingeschlossene Funktion nur Lesezugriff auf die geerbten Variablen, kann ihnen jedoch keine Zuweisungen vornehmen

def makeInc(x):
  def inc(y):
     # incrementing x is not allowed
     x += y  
     return x

  return inc

incOne = makeInc(1)
incOne(5) # UnboundLocalError: local variable 'x' referenced before assignment

Python 3 bietet die nonlocal Anweisung ( Nonlocal Variables ) zum Realisieren eines vollständigen Schließens mit verschachtelten Funktionen.

Python 3.x 3.0
def makeInc(x):
  def inc(y):
     nonlocal x
     # now assigning a value to x is allowed
     x += y  
     return x

  return inc

incOne = makeInc(1)
incOne(5) # returns 6

Rekursive Funktionen

Eine rekursive Funktion ist eine Funktion, die sich in ihrer Definition aufruft. Zum Beispiel die mathematische Funktion Faktorial, definiert durch factorial(n) = n*(n-1)*(n-2)*...*3*2*1 . kann als programmiert werden

def factorial(n):
    #n here should be an integer
    if n == 0:
        return 1
    else:
        return n*factorial(n-1)

Die Ausgänge hier sind:

factorial(0)
#out 1
factorial(1)
#out 1
factorial(2)
#out 2
factorial(3)
#out 6

wie erwartet. Beachten Sie, dass diese Funktion rekursiv ist, da die zweite return factorial(n-1) die Funktion in ihrer Definition aufruft.

Einige rekursive Funktionen können mit Lambda implementiert werden, die faktorielle Funktion mit Lambda wäre etwa so:

factorial = lambda n: 1 if n == 0 else n*factorial(n-1)

Die Funktion wird wie oben ausgegeben.

Rekursionslimit

Die Tiefe der möglichen Rekursion ist begrenzt, abhängig von der Python-Implementierung. Wenn der Grenzwert erreicht ist, wird eine RuntimeError-Ausnahme ausgelöst:

def cursing(depth):
  try:
    cursing(depth + 1) # actually, re-cursing
  except RuntimeError as RE:
    print('I recursed {} times!'.format(depth))

cursing(0)
# Out: I recursed 1083 times!

Sie können den Grenzwert für die Rekursionstiefe mithilfe von sys.setrecursionlimit(limit) ändern und diesen Grenzwert mit sys.getrecursionlimit() überprüfen.

sys.setrecursionlimit(2000)
cursing(0)
# Out: I recursed 1997 times!

Bei Python 3.5 ist die Ausnahme ein RecursionError , der von RuntimeError abgeleitet RuntimeError .

Verschachtelte Funktionen

Funktionen in Python sind erstklassige Objekte. Sie können in beliebigem Umfang definiert werden

def fibonacci(n):
    def step(a,b):
        return b, a+b
    a, b = 0, 1
    for i in range(n):
        a, b = step(a, b)
    return a

Funktionen, die ihren einschließenden Bereich erfassen, können wie andere Objekte weitergegeben werden

def make_adder(n):
    def adder(x):
        return n + x
    return adder
add5 = make_adder(5)
add6 = make_adder(6)
add5(10)
#Out: 15
add6(10)
#Out: 16

def repeatedly_apply(func, n, x):
    for i in range(n):
        x = func(x)
    return x

repeatedly_apply(add5, 5, 1)
#Out: 26

Iterable und Wörterbuch auspacken

Mit Funktionen können Sie folgende Arten von Parametern angeben: positional, named, variable positional, Keyword args (kwargs). Hier ist eine klare und prägnante Verwendung jedes Typs.

def unpacking(a, b, c=45, d=60, *args, **kwargs):
    print(a, b, c, d, args, kwargs)

>>> unpacking(1, 2)
1 2 45 60 () {}
>>> unpacking(1, 2, 3, 4)
1 2 3 4 () {}
>>> unpacking(1, 2, c=3, d=4)
1 2 3 4 () {}
>>> unpacking(1, 2, d=4, c=3)
1 2 3 4 () {}


>>> pair = (3,)
>>> unpacking(1, 2, *pair, d=4)
1 2 3 4 () {}
>>> unpacking(1, 2, d=4, *pair)
1 2 3 4 () {}
>>> unpacking(1, 2, *pair, c=3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
>>> unpacking(1, 2, c=3, *pair)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'

>>> args_list = [3]
>>> unpacking(1, 2, *args_list, d=4)
1 2 3 4 () {}
>>> unpacking(1, 2, d=4, *args_list)
1 2 3 4 () {}
>>> unpacking(1, 2, c=3, *args_list)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'
>>> unpacking(1, 2, *args_list, c=3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'


>>> pair = (3, 4)
>>> unpacking(1, 2, *pair)
1 2 3 4 () {}
>>> unpacking(1, 2, 3, 4, *pair)
1 2 3 4 (3, 4) {}
>>> unpacking(1, 2, d=4, *pair)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
>>> unpacking(1, 2, *pair, d=4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'



>>> args_list = [3, 4]
>>> unpacking(1, 2, *args_list)
1 2 3 4 () {}
>>> unpacking(1, 2, 3, 4, *args_list)
1 2 3 4 (3, 4) {}
>>> unpacking(1, 2, d=4, *args_list)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
>>> unpacking(1, 2, *args_list, d=4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'


>>> arg_dict = {'c':3, 'd':4}
>>> unpacking(1, 2, **arg_dict)
1 2 3 4 () {}
>>> arg_dict = {'d':4, 'c':3}
>>> unpacking(1, 2, **arg_dict)
1 2 3 4 () {}
>>> arg_dict = {'c':3, 'd':4, 'not_a_parameter': 75}
>>> unpacking(1, 2, **arg_dict)
1 2 3 4 () {'not_a_parameter': 75}


>>> unpacking(1, 2, *pair, **arg_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'
>>> unpacking(1, 2, 3, 4, **arg_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'd'

# Positional arguments take priority over any other form of argument passing
>>> unpacking(1, 2, **arg_dict, c=3)
1 2 3 4 () {'not_a_parameter': 75}
>>> unpacking(1, 2, 3, **arg_dict, c=3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unpacking() got multiple values for argument 'c'

Erzwingen die Verwendung benannter Parameter

Alle Parameter, die nach dem ersten Stern in der Funktionssignatur angegeben werden, sind nur ein Schlüsselwort.

def f(*a, b):
    pass

f(1, 2, 3)
# TypeError: f() missing 1 required keyword-only argument: 'b'

In Python 3 ist es möglich, ein einzelnes Sternchen in die Funktionssignatur einzufügen, um sicherzustellen, dass die verbleibenden Argumente nur mit Schlüsselwortargumenten übergeben werden.

def f(a, b, *, c):
    pass

f(1, 2, 3)
# TypeError: f() takes 2 positional arguments but 3 were given
f(1, 2, c=3)
# No error

Rekursives Lambda mit zugewiesener Variable

Eine Methode zum Erstellen rekursiver Lambda-Funktionen umfasst das Zuweisen der Funktion zu einer Variablen und das anschließende Referenzieren dieser Variablen innerhalb der Funktion selbst. Ein häufiges Beispiel hierfür ist die rekursive Berechnung der Fakultät einer Zahl - wie im folgenden Code dargestellt:

lambda_factorial = lambda i:1 if i==0 else i*lambda_factorial(i-1)
print(lambda_factorial(4)) # 4 * 3 * 2 * 1 = 12 * 2 = 24

Beschreibung des Codes

Die Lambda - Funktion, durch seine variable Zuordnung wird ein Wert (4) übergeben , die sie auswertet und gibt 1 zurück , wenn es 0 ist , sonst gibt er den aktuellen Wert ( i ) * eine andere Berechnung durch die Lambda - Funktion des Wertes - 1 ( i-1 ). Dies wird fortgesetzt, bis der übergebene Wert auf 0 dekrementiert ist ( return 1 ). Ein Prozess, der visualisiert werden kann als:

recursive_lambda_path



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow