Python Language
Funktionen
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
- Mehr über Funktionen und Dekorateure: https://www.thecodeship.com/patterns/guide-to-python-function-decorators/
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 einTypeError
. Es kann als positionelles (func(10)
) oder Schlüsselwortargumentfunc(arg1=10)
) angegeben werden. -
kwarg1
muss ebenfalls angegeben werden, es kann jedoch nur als Schlüsselwortargument angegeben werden:func(kwarg1=10)
. -
arg2
undkwarg2
sind optional. Wenn der Wert geändert werden soll, gelten die gleichen Regeln wie fürarg1
(entweder positional oder Schlüsselwort) undkwarg1
(nur Schlüsselwort). -
*args
fängt zusätzliche Positionsparameter ab. Beachten Sie jedoch, dassarg1
undarg2
als Positionsargumentearg2
müssen, um Argumente an*args
:func(1, 1, 1, 1)
. -
**kwargs
alle zusätzlichen Schlüsselwortparameter. In diesem Fall ein Parameter, der nichtarg1
,arg2
,kwarg1
oderkwarg2
. 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 diemath.isclose
Funktion in Python 3.5 und höher mitdef math.isclose (a, b, *, rel_tol=1e-09, abs_tol=0.0)
definiertdef 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 explizitendef
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.
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: