Normale Argumente vs. Schlüsselwortargumente

289

Wie unterscheiden sich "Schlüsselwortargumente" von regulären Argumenten? Können nicht alle Argumente als name=valueanstelle der Positionssyntax übergeben werden?

mk12
quelle
6
Vielleicht möchten Sie auch PEP 3102 lesen - sie räumen einige dieser Dinge
Ben Hoyt
Und ob es einen Standardwert gibt oder nicht, hat nichts damit zu tun (außer ob Sie einen Wert dafür übergeben müssen oder nicht), oder?
mk12
Lesen Sie mehr über Python Positional / Keyword Argumente
Ducin
@ Ben Hoyt Hinzugefügt eine Antwort für Python 3, erforderliche Schlüsselwortargumente
Christophe Roussy

Antworten:

346

Es gibt zwei verwandte Konzepte, die beide als " Schlüsselwortargumente " bezeichnet werden.

Auf der aufrufenden Seite, wie andere Kommentatoren erwähnt haben, können Sie einige Funktionsargumente nach Namen angeben. Sie müssen sie nach allen Argumenten ohne Namen ( Positionsargumente ) erwähnen , und es müssen Standardwerte für alle Parameter vorhanden sein, die überhaupt nicht erwähnt wurden.

Das andere Konzept ist auf der Seite der Funktionsdefinition: Sie können eine Funktion definieren, die Parameter nach Namen nimmt - und Sie müssen nicht einmal angeben, wie diese Namen lauten. Dies sind reine Schlüsselwortargumente und können nicht positionell übergeben werden. Die Syntax lautet

def my_function(arg1, arg2, **kwargs)

Alle Schlüsselwortargumente, die Sie an diese Funktion übergeben, werden in ein Wörterbuch mit dem Namen eingefügt kwargs. Sie können die Schlüssel dieses Wörterbuchs zur Laufzeit folgendermaßen untersuchen:

def my_function(**kwargs):
    print str(kwargs)

my_function(a=12, b="abc")

{'a': 12, 'b': 'abc'}
Ian Clelland
quelle
5
+1 und akzeptiert: Sie sind der einzige, der über beide Arten von Positions- + Schlüsselwortargumenten gesprochen hat. Alle anderen dachten entweder, ich spreche über das erste oder das zweite (aber es waren immer noch gute Beiträge). Vielen Dank!
mk12
34
Der Wortlaut ist unklar: Normalerweise spricht man von Argumenten auf der aufrufenden Seite und von Parametern auf der aufgerufenen Seite.
glglgl
3
Muss der Parametername sein kwargsoder kann ich ihn in etw umbenennen? wie options( def my_fuction(arg1, arg2, **options))?
Bruce Sun
1
Der Name kann alles sein, kwargsist aber die Konvention, wenn es keinen passenderen Namen gibt
Matt Zimmerman
Ich denke, das zweite hier erläuterte Konzept wird technisch als Arbitrary Keyword Arguments bezeichnet.
Anshul Dahiya
188

Es gibt ein letztes Sprachmerkmal, bei dem die Unterscheidung wichtig ist. Betrachten Sie die folgende Funktion:

def foo(*positional, **keywords):
    print "Positional:", positional
    print "Keywords:", keywords

Das *positionalArgument speichert alle an übergebenen Positionsargumente foo(), ohne die Anzahl der von Ihnen angegebenen zu begrenzen.

>>> foo('one', 'two', 'three')
Positional: ('one', 'two', 'three')
Keywords: {}

Das **keywordsArgument speichert alle Schlüsselwortargumente:

>>> foo(a='one', b='two', c='three')
Positional: ()
Keywords: {'a': 'one', 'c': 'three', 'b': 'two'}

Und natürlich können Sie beide gleichzeitig verwenden:

>>> foo('one','two',c='three',d='four')
Positional: ('one', 'two')
Keywords: {'c': 'three', 'd': 'four'}

Diese Funktionen werden selten verwendet, sind jedoch gelegentlich sehr nützlich, und es ist wichtig zu wissen, welche Argumente Positions- oder Schlüsselwörter sind.

zu viel php
quelle
3
Hervorragende Antwort! Nur eine Anmerkung, dass erforderliche Positionsargumente vorher übergeben werden können *positionalund **keywordswenn wir die Funktionsdefinition wie ändern def foo(arg1, *positional, **keywords):. Hier arg1ist positionell und erforderlich. Bitte beachten Sie, dass die Position in der Antwort eine optionale und variable Anzahl von Positionsargumenten bedeutet.
Shaffooo
2
Ja, gute Antwort. Noch ein Hinweis: Wenn Sie Ihre Funktion aufrufen foo(bar=True), können Sie die Werte mit bar = keywords.pop('bar')denselben wie erhalten bar = keywords.pop('bar', None). Verwenden Sie als Standardwertbar = keywords.pop('bar', False)
olibre
111

Die Verwendung von Schlüsselwortargumenten ist dasselbe wie normale Argumente, außer dass die Reihenfolge keine Rolle spielt. Zum Beispiel sind die beiden folgenden Funktionsaufrufe gleich:

def foo(bar, baz):
    pass

foo(1, 2)
foo(baz=2, bar=1)
Eli Gray
quelle
3
Danke dafür. Es ist unglaublich nützlich , dass ich sowohl ein Schlüsselwort arg als Positions arg geben und eine Positions arg als Schlüsselwort arg.
Luke Davis
47

Positionsargumente

Sie haben keine Schlüsselwörter vor sich. Die Reihenfolge ist wichtig!

func(1,2,3, "foo")

Schlüsselwortargumente

Sie haben Schlüsselwörter in der Front. Sie können in beliebiger Reihenfolge sein!

func(foo="bar", baz=5, hello=123)

func(baz=5, foo="bar", hello=123)

Sie sollten auch wissen, dass die Reihenfolge wichtig ist, wenn Sie Standardargumente verwenden und das Einfügen der Schlüsselwörter vernachlässigen!

def func(foo=1, baz=2, hello=3): ...
func("bar", 5, 123)
Unbekannt
quelle
8
IMHO ist das 3. Beispiel (Standardargumente) nicht klar. Ich denke, Sie sprechen darüber, was passiert, wenn ein oder mehrere Parameter Standardwerte deklarieren und der Aufruf die Positionsnotation verwendet, aber WENIGER als die Anzahl der deklarierten Parameter liefert. In Ihrem Beispiel sind jedoch 3 deklariert und 3 im Aufruf, sodass die Standardwerte überhaupt keine Auswirkung haben! Wollten Sie das 3. Argument weglassen? zB func("bar", 5)? Und dann sagen, das hellobekommt seinen Standardwert von 3.
ToolmakerSteve
25

Es gibt zwei Möglichkeiten, Funktionsparametern Argumentwerte zuzuweisen. Beide werden verwendet.

  1. Nach Position. Positionsargumente haben keine Schlüsselwörter und werden zuerst zugewiesen.

  2. Nach Stichwort. Schlüsselwortargumente haben Schlüsselwörter und werden nach Positionsargumenten an zweiter Stelle zugewiesen.

Beachten Sie, dass Sie die Option haben, Positionsargumente zu verwenden.

Wenn Sie keine Positionsargumente verwenden, stellt sich heraus, dass alles , was Sie geschrieben haben, ein Schlüsselwortargument ist.

Wenn Sie eine Funktion aufrufen, entscheiden Sie sich für die Verwendung von Position, Schlüsselwort oder einer Mischung. Sie können alle Schlüsselwörter auswählen, wenn Sie möchten. Einige von uns treffen diese Wahl nicht und verwenden Positionsargumente.

S.Lott
quelle
1
Ohh, ich dachte an Parameter, wenn es tatsächlich um die Argumente geht (was ich übergebe). Vielen Dank!
mk12
24

Ich bin überrascht, dass niemand darauf hingewiesen zu haben scheint, dass man ein Wörterbuch mit Parametern mit Schlüsselargumenten übergeben kann, die die formalen Parameter erfüllen.

>>> def func(a='a', b='b', c='c', **kwargs):
...    print 'a:%s, b:%s, c:%s' % (a, b, c)
... 
>>> func()
a:a, b:b, c:c
>>> func(**{'a' : 'z', 'b':'q', 'c':'v'})
a:z, b:q, c:v
>>> 
Sherman
quelle
11
+1 für eine nützliche Technik. Ihr Punkt wäre klarer, ohne , **kwargs. Dies würde zeigen, dass sogar eine einfache func def mit einer festen Anzahl von Parametern ein Wörterbuch liefern kann. Das heißt, es erfordert nichts Besonderes in der Definition. DANN können Sie ein zweites Beispiel hinzufügen, WITH ** kwargs in der Definition, und zeigen, wie EXTRA-Elemente im Wörterbuch darüber verfügbar sind.
ToolmakerSteve
1
Ich habe dies im Quellcode verschiedener Bibliotheken gesehen und war so verwirrt. Danke, dass du es geklärt hast!
Craig Labenz
3
Der vierte formale Parameter oben - ** kwargs ist erforderlich, wenn Sie func jemals mit einem Wörterbuch aufrufen, das andere Schlüssel als 'a', 'b' und 'c' enthält.
Eduardo
Für mich print 'a:%s, b:%s, c:%s' % (a, b, c)gibt es Syntaxfehler, print('a:%s, b:%s, c:%s' % (a, b, c))funktioniert aber. Etwas mit Python-Version? Trotzdem danke für diesen Einblick, bis jetzt habe ich den print('a:{}, b:{}, c:{}'.format(a, b, c))
klobigeren benutzt
17

Mit 3 Python Sie können beide erforderlich und nicht erforderlich Schlüsselwort Argumente :


Optional : (Standardwert für Parameter 'b' definiert)

def func1(a, *, b=42):
    ...
func1(value_for_a) # b is optional and will default to 42

Erforderlich (kein Standardwert für Parameter 'b' definiert):

def func2(a, *, b):
    ... 
func2(value_for_a, b=21) # b is set to 21 by the function call
func2(value_for_a) # ERROR: missing 1 required keyword-only argument: 'b'`

Dies kann in Fällen hilfreich sein, in denen viele ähnliche Argumente nebeneinander stehen, insbesondere wenn sie vom gleichen Typ sind. In diesem Fall bevorzuge ich die Verwendung benannter Argumente oder erstelle eine benutzerdefinierte Klasse, wenn Argumente zusammengehören.

Christophe Roussy
quelle
3
Die erforderliche Variante ist sehr nützlich. Es wird dringend empfohlen, die Argumente namentlich anzugeben, ohne Standardeinstellungen anzugeben, was häufig keinen Sinn ergibt.
TNT
Standardwerte sehen gut aus und können Ihnen beim Start Zeit sparen, aber auf lange Sicht können Standardwerte eine PITA sein.
Christophe Roussy
11

Ich bin überrascht, dass niemand die Tatsache erwähnt hat, dass Sie Positions- und Schlüsselwortargumente mischen können, um hinterhältige Dinge wie diese mit *argsund **kwargs( von dieser Site ) zu tun :

def test_var_kwargs(farg, **kwargs):
    print "formal arg:", farg
    for key in kwargs:
        print "another keyword arg: %s: %s" % (key, kwargs[key])

Auf diese Weise können Sie beliebige Schlüsselwortargumente verwenden, die möglicherweise Schlüssel enthalten, die Sie nicht im Voraus definieren möchten.

Gabriel Hurley
quelle
0

Ich suchte nach einem Beispiel mit Standard-Warns mithilfe von Typanmerkungen:

def test_var_kwarg(a: str, b: str='B', c: str='', **kwargs) -> str:
     return ' '.join([a, b, c, str(kwargs)])

Beispiel:

>>> print(test_var_kwarg('A', c='okay'))
A B okay {}
>>> d = {'f': 'F', 'g': 'G'}
>>> print(test_var_kwarg('a', c='c', b='b', **d))
a b c {'f': 'F', 'g': 'G'}
>>> print(test_var_kwarg('a', 'b', 'c'))
a b c {}
jmunsch
quelle
0

Fügen Sie einfach eine Möglichkeit zum Definieren des Standardwerts von Argumenten hinzu, die beim Aufrufen der Funktion nicht in Schlüsselwörtern zugewiesen werden:

def func(**keywargs):
if 'my_word' not in keywargs:
    word = 'default_msg'
else:
    word = keywargs['my_word']
return word

Nennen Sie dies durch:

print(func())
print(func(my_word='love'))

Du wirst kriegen:

default_msg
love

Lesen Sie mehr über *argsund **kwargsin Python: https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3

sonictl
quelle