Was tun ** (Doppelstern / Sternchen) und * (Stern / Sternchen) für Parameter?

2350

In den folgenden Verfahren Definitionen, was bedeutet das *und **tut für param2?

def foo(param1, *param2):
def bar(param1, **param2):
Todd
quelle
4
Siehe auch stackoverflow.com/questions/6967632/…
Aaron Hall
Siehe auch stackoverflow.com/questions/14301967/… für ein nacktes Sternchen
naught101
24
Diese Frage ist ein sehr beliebtes doppeltes Ziel, wird aber leider oft falsch verwendet. Beachten Sie, dass in dieser Frage nach dem Definieren von Funktionen mit varargs ( def func(*args)) gefragt wird . Für eine Frage zu fragen , was es bedeutet , in Funktion Anrufen ( func(*[1,2])) siehe hier . Für eine Frage zu stellen , wie Argumentlisten sehen auspacken hier . Für eine Frage, was die Bedeutung *in Literalen ( [*[1, 2]]) bedeutet, siehe hier .
Aran-Fey
Informationen zur
Akshay Anurag

Antworten:

2237

Das *argsund **kwargsist eine gebräuchliche Redewendung, um eine beliebige Anzahl von Argumenten für Funktionen zuzulassen, wie im Abschnitt über das Definieren von Funktionen in der Python-Dokumentation beschrieben.

Das *argsgibt Ihnen alle Funktionsparameter als Tupel :

def foo(*args):
    for a in args:
        print(a)        

foo(1)
# 1

foo(1,2,3)
# 1
# 2
# 3

Das **kwargsgibt Ihnen alle Schlüsselwortargumente mit Ausnahme derjenigen, die einem formalen Parameter als Wörterbuch entsprechen.

def bar(**kwargs):
    for a in kwargs:
        print(a, kwargs[a])  

bar(name='one', age=27)
# age 27
# name one

Beide Redewendungen können mit normalen Argumenten gemischt werden, um eine Reihe fester und einiger variabler Argumente zu ermöglichen:

def foo(kind, *args, **kwargs):
   pass

Es ist auch möglich, dies umgekehrt zu verwenden:

def foo(a, b, c):
    print(a, b, c)

obj = {'b':10, 'c':'lee'}

foo(100,**obj)
# 100 10 lee

Eine andere Verwendung des *lIdioms besteht darin, beim Aufrufen einer Funktion Argumentlisten zu entpacken .

def foo(bar, lee):
    print(bar, lee)

l = [1,2]

foo(*l)
# 1 2

In Python 3 ist es möglich, *lauf der linken Seite einer Zuweisung ( Extended Iterable Unpacking ) zu verwenden, obwohl in diesem Kontext eine Liste anstelle eines Tupels angezeigt wird :

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

Auch Python 3 fügt eine neue Semantik hinzu (siehe PEP 3102 ):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
    pass

Eine solche Funktion akzeptiert nur 3 Positionsargumente, und alles danach *kann nur als Schlüsselwortargumente übergeben werden.

Peter Hoffmann
quelle
9
Die Ausgabe von [6] erfolgt in umgekehrter Reihenfolge. Name ein Alter 27
thanos.a
54
@ thanos.a Python-Dikte, die semantisch für die Übergabe von Schlüsselwortargumenten verwendet werden, sind willkürlich angeordnet. In Python 3.6 wird jedoch garantiert, dass Schlüsselwortargumente die Einfügereihenfolge speichern. "Die Reihenfolge der Elemente in **kwargsentspricht jetzt der Reihenfolge, in der Schlüsselwortargumente an die Funktion übergeben wurden." - docs.python.org/3/whatsnew/3.6.html Tatsächlich werden alle Dikte in CPython 3.6 die Einfügereihenfolge als Implementierungsdetail speichern. Dies wird in Python 3.7 zum Standard.
Aaron Hall
13
Sehr präzise, ​​sauber und leicht zu verstehen. Ich weiß es zu schätzen, dass Sie bemerkt haben, dass es sich um einen "Auspack-Operator" handelt, so dass ich mich von der Referenzübergabe in C unterscheiden kann. +1
bballdave025
Wie teste ich die letzte Funktion mit PEP 3102? Ich nenne es mit func (1,2,3, name = "me", age = 10) und es löst eine Ausnahme aus:got an unexpected keyword argument 'name'
Kok How Teh
@KokHowTeh Sie müssen die benannten kwargs so übergeben, wie sie in der Funktion sind: func (1, 2, 3, kwarg1 = 'ich', kwarg2 = 10)
John Aaron
622

Es ist auch erwähnenswert, dass Sie *und **beim Aufrufen von Funktionen auch verwenden können. Dies ist eine Verknüpfung, mit der Sie mehrere Argumente direkt über eine Liste / ein Tupel oder ein Wörterbuch an eine Funktion übergeben können. Zum Beispiel, wenn Sie die folgende Funktion haben:

def foo(x,y,z):
    print("x=" + str(x))
    print("y=" + str(y))
    print("z=" + str(z))

Sie können Dinge tun wie:

>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3

>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3

>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3

Hinweis: Die Tasten mydictmüssen genau wie die Funktionsparameter benannt werden foo. Andernfalls wird ein TypeError:

>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'
Lorin Hochstein
quelle
175

Das einzelne * bedeutet, dass es beliebig viele zusätzliche Positionsargumente geben kann. foo()kann wie aufgerufen werden foo(1,2,3,4,5). Im Körper von foo () ist param2 eine Sequenz, die 2-5 enthält.

Das doppelte ** bedeutet, dass es eine beliebige Anzahl von zusätzlichen benannten Parametern geben kann. bar()kann wie aufgerufen werden bar(1, a=2, b=3). Im Hauptteil von bar () param2 befindet sich ein Wörterbuch mit {'a': 2, 'b': 3}

Mit folgendem Code:

def foo(param1, *param2):
    print(param1)
    print(param2)

def bar(param1, **param2):
    print(param1)
    print(param2)

foo(1,2,3,4,5)
bar(1,a=2,b=3)

die Ausgabe ist

1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}
nickd
quelle
5
Möglicherweise wird ein zusätzliches Beispiel mit foobar(param1, *param2, **param3)benötigt, um diese Antwort zu vervollständigen.
Aniket Thakur
1
@AniketThakur hat den restlichen Teil hier hinzugefügt .
Raj
148

Was tun **(Doppelstern) und *(Stern) für Parameter ?

Sie ermöglichen die Definition von Funktionen zur Annahme und die Übergabe einer beliebigen Anzahl von Argumenten, positional ( *) und keyword ( **).

Funktionen definieren

*argsermöglicht eine beliebige Anzahl optionaler Positionsargumente (Parameter), die einem Tupel mit dem Namen zugewiesen werden args.

**kwargsermöglicht eine beliebige Anzahl von optionalen Schlüsselwortargumenten (Parametern), die in einem Diktat mit dem Namen enthalten sind kwargs.

Sie können (und sollten) einen geeigneten Namen auswählen, aber wenn die Argumente eine unspezifische Semantik haben sollen argsund kwargsStandardnamen sind.

Erweiterung, Übergabe einer beliebigen Anzahl von Argumenten

Sie können auch verwendet werden *argsund **kwargsjeweils in den Parametern aus den Listen (oder jede iterable) und dicts (oder jedes mapping), zu übergeben.

Die Funktion, die die Parameter empfängt, muss nicht wissen, dass sie erweitert werden.

Zum Beispiel erwartet der xrange von Python 2 nicht explizit *args, aber da 3 Ganzzahlen als Argumente verwendet werden:

>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x)    # expand here
xrange(0, 2, 2)

Als weiteres Beispiel können wir die Dikt-Erweiterung verwenden in str.format:

>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'

Neu in Python 3: Funktionen mit Argumenten definieren, die nur Schlüsselwörter enthalten

Sie können nur Schlüsselwortargumente verwenden, nachdem *args- beispielsweise hier kwarg2als Schlüsselwortargument angegeben werden muss - nicht positionell:

def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): 
    return arg, kwarg, args, kwarg2, kwargs

Verwendungszweck:

>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})

Auch *selbst kann verwendet werden , um anzuzeigen , dass nur ein Schlüsselwort Argument folgen, ohne dass für unbegrenzte Positionsargumente.

def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): 
    return arg, kwarg, kwarg2, kwargs

Auch hier kwarg2muss es sich um ein explizit benanntes Schlüsselwortargument handeln:

>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})

Und wir können keine unbegrenzten Positionsargumente mehr akzeptieren, weil wir nicht haben *args*:

>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments 
    but 5 positional arguments (and 1 keyword-only argument) were given

Auch hier müssen wir einfacher gesagt kwargnamentlich und nicht positionell angegeben werden:

def bar(*, kwarg=None): 
    return kwarg

In diesem Beispiel sehen wir, dass beim Versuch, die kwargPosition zu bestehen, eine Fehlermeldung angezeigt wird:

>>> bar('kwarg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given

Wir müssen den kwargParameter explizit als Schlüsselwortargument übergeben.

>>> bar(kwarg='kwarg')
'kwarg'

Python 2-kompatible Demos

*args(normalerweise "star-args" genannt) und **kwargs(Sterne können durch das Aussprechen von "kwargs" impliziert werden, aber mit "double star kwargs" explizit angegeben werden) sind gängige Redewendungen von Python für die Verwendung der *und **-Notation. Diese spezifischen Variablennamen sind nicht erforderlich (z. B. könnten Sie *foosund verwenden **bars), aber eine Abweichung von der Konvention kann Ihre Python-Codierkollegen wahrscheinlich verärgern.

Wir verwenden diese normalerweise, wenn wir nicht wissen, was unsere Funktion erhalten wird oder wie viele Argumente wir möglicherweise übergeben, und manchmal sogar, wenn jede Variable separat benannt wird, dies sehr chaotisch und redundant wird (dies ist jedoch ein Fall, in dem dies normalerweise explizit ist besser als implizit).

Beispiel 1

Die folgende Funktion beschreibt, wie sie verwendet werden können, und demonstriert das Verhalten. Beachten Sie, dass das genannte bArgument vom zweiten Positionsargument vor verwendet wird:

def foo(a, b=10, *args, **kwargs):
    '''
    this function takes required argument a, not required keyword argument b
    and any number of unknown positional arguments and keyword arguments after
    '''
    print('a is a required argument, and its value is {0}'.format(a))
    print('b not required, its default value is 10, actual value: {0}'.format(b))
    # we can inspect the unknown arguments we were passed:
    #  - args:
    print('args is of type {0} and length {1}'.format(type(args), len(args)))
    for arg in args:
        print('unknown arg: {0}'.format(arg))
    #  - kwargs:
    print('kwargs is of type {0} and length {1}'.format(type(kwargs),
                                                        len(kwargs)))
    for kw, arg in kwargs.items():
        print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
    # But we don't have to know anything about them 
    # to pass them to other functions.
    print('Args or kwargs can be passed without knowing what they are.')
    # max can take two or more positional args: max(a, b, c...)
    print('e.g. max(a, b, *args) \n{0}'.format(
      max(a, b, *args))) 
    kweg = 'dict({0})'.format( # named args same as unknown kwargs
      ', '.join('{k}={v}'.format(k=k, v=v) 
                             for k, v in sorted(kwargs.items())))
    print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
      dict(**kwargs), kweg=kweg))

Wir können in der Online-Hilfe nach der Signatur der Funktion suchen, mit help(foo)der es uns sagt

foo(a, b=10, *args, **kwargs)

Nennen wir diese Funktion mit foo(1, 2, 3, 4, e=5, f=6, g=7)

welche druckt:

a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns: 
{'e': 5, 'g': 7, 'f': 6}

Beispiel 2

Wir können es auch mit einer anderen Funktion aufrufen, die wir nur bereitstellen a:

def bar(a):
    b, c, d, e, f = 2, 3, 4, 5, 6
    # dumping every local variable into foo as a keyword argument 
    # by expanding the locals dict:
    foo(**locals()) 

bar(100) Drucke:

a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns: 
{'c': 3, 'e': 5, 'd': 4, 'f': 6}

Beispiel 3: Praktische Anwendung bei Dekorateuren

OK, vielleicht sehen wir das Dienstprogramm noch nicht. Stellen Sie sich vor, Sie haben mehrere Funktionen mit redundantem Code vor und / oder nach dem Differenzierungscode. Die folgenden benannten Funktionen sind nur zur Veranschaulichung Pseudocode.

def foo(a, b, c, d=0, e=100):
    # imagine this is much more code than a simple function call
    preprocess() 
    differentiating_process_foo(a,b,c,d,e)
    # imagine this is much more code than a simple function call
    postprocess()

def bar(a, b, c=None, d=0, e=100, f=None):
    preprocess()
    differentiating_process_bar(a,b,c,d,e,f)
    postprocess()

def baz(a, b, c, d, e, f):
    ... and so on

Wir könnten in der Lage sein, dies anders zu handhaben, aber wir können die Redundanz mit einem Dekorateur auf jeden Fall extrahieren, und so zeigt unser unten stehendes Beispiel, wie *argsund **kwargssehr nützlich sein kann:

def decorator(function):
    '''function to wrap other functions with a pre- and postprocess'''
    @functools.wraps(function) # applies module, name, and docstring to wrapper
    def wrapper(*args, **kwargs):
        # again, imagine this is complicated, but we only write it once!
        preprocess()
        function(*args, **kwargs)
        postprocess()
    return wrapper

Und jetzt kann jede umschlossene Funktion viel prägnanter geschrieben werden, da wir die Redundanz herausgerechnet haben:

@decorator
def foo(a, b, c, d=0, e=100):
    differentiating_process_foo(a,b,c,d,e)

@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
    differentiating_process_bar(a,b,c,d,e,f)

@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
    differentiating_process_baz(a,b,c,d,e,f, g)

@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
    differentiating_process_quux(a,b,c,d,e,f,g,h)

Und durch unseren Code Ausklammern, die *argsund **kwargsuns erlaubt , zu tun, reduzieren wir Codezeilen, die Verbesserung der Lesbarkeit und Wartbarkeit und die alleinige kanonische Standorte für die Logik in unserem Programm. Wenn wir einen Teil dieser Struktur ändern müssen, haben wir einen Ort, an dem wir jede Änderung vornehmen können.

Aaron Hall
quelle
48

Lassen Sie uns zunächst verstehen, was Positionsargumente und Schlüsselwortargumente sind. Unten finden Sie ein Beispiel für die Funktionsdefinition mit Positionsargumenten.

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(1,2,3)
#output:
1
2
3

Dies ist also eine Funktionsdefinition mit Positionsargumenten. Sie können es auch mit Schlüsselwort / benannten Argumenten aufrufen:

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(a=1,b=2,c=3)
#output:
1
2
3

Lassen Sie uns nun ein Beispiel für die Funktionsdefinition mit Schlüsselwortargumenten untersuchen :

def test(a=0,b=0,c=0):
     print(a)
     print(b)
     print(c)
     print('-------------------------')

test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------

Sie können diese Funktion auch mit Positionsargumenten aufrufen:

def test(a=0,b=0,c=0):
    print(a)
    print(b)
    print(c)
    print('-------------------------')

test(1,2,3)
# output :
1
2
3
---------------------------------

So kennen wir jetzt Funktionsdefinitionen mit Positions- und Schlüsselwortargumenten.

Lassen Sie uns nun den Operator '*' und den Operator '**' untersuchen.

Bitte beachten Sie, dass diese Operatoren in 2 Bereichen verwendet werden können:

a) Funktionsaufruf

b) Funktionsdefinition

Die Verwendung von '*' Operator und '**' Operator im Funktionsaufruf.

Kommen wir gleich zu einem Beispiel und diskutieren es dann.

def sum(a,b):  #receive args from function calls as sum(1,2) or sum(a=1,b=2)
    print(a+b)

my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}

# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple)   # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list)    # becomes same as sum(1,2) after unpacking my_list with  '*'
sum(**my_dict)   # becomes same as sum(a=1,b=2) after unpacking by '**' 

# output is 3 in all three calls to sum function.

Also denk daran

wenn der Operator '*' oder '**' in einem Funktionsaufruf verwendet wird -

Der Operator '*' entpackt Datenstrukturen wie eine Liste oder ein Tupel in Argumente, die für die Funktionsdefinition benötigt werden.

Der Operator '**' entpackt ein Wörterbuch in Argumente, die für die Funktionsdefinition benötigt werden.

Lassen Sie uns nun die Verwendung des Operators '*' in der Funktionsdefinition untersuchen . Beispiel:

def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
    sum = 0
    for a in args:
        sum+=a
    print(sum)

sum(1,2,3,4)  #positional args sent to function sum
#output:
10

In Funktion Definition des ‚*‘ Operator - Pack , die empfangenen Argumente in ein Tupel.

Lassen Sie uns nun ein Beispiel für '**' sehen, das in der Funktionsdefinition verwendet wird:

def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
    sum=0
    for k,v in args.items():
        sum+=v
    print(sum)

sum(a=1,b=2,c=3,d=4) #positional args sent to function sum

In Funktion Definition des ‚**‘ Operator - Pack , die empfangenen Argumente in ein Wörterbuch.

Also denk daran:

In einem Funktionsaufruf entpackt das '*' die Datenstruktur von Tupel oder Liste in Positions- oder Schlüsselwortargumente, die von der Funktionsdefinition empfangen werden sollen.

In einem Funktionsaufruf entpackt das '**' die Datenstruktur des Wörterbuchs in Positions- oder Schlüsselwortargumente, die von der Funktionsdefinition empfangen werden sollen.

In einer Funktionsdefinition packt das '*' Positionsargumente in ein Tupel.

In einer Funktionsdefinition packt das '**' Schlüsselwortargumente in ein Wörterbuch.

Karan Ahuja
quelle
Wirklich sauber, Schritt für Schritt und leicht zu befolgende Erklärung!
Aleksandar
danke Lass die Upvotes kommen. [Auch für weitere Notizen von mir bin ich bei @mrtechmaker auf Twitter]
Karan Ahuja
32

Diese Tabelle ist praktisch für die Verwendung *und **Funktion Aufbau und Funktion Aufruf :

            In function construction         In function call
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

Dies dient wirklich nur dazu, Lorin Hochsteins Antwort zusammenzufassen, aber ich finde es hilfreich.

Im Zusammenhang damit: Verwendungen für die Stern- / Splat Operatoren wurden erweitert in Python 3

Brad Solomon
quelle
22

*und **haben eine besondere Verwendung in der Liste der Funktionsargumente. * impliziert, dass das Argument eine Liste ist und **dass das Argument ein Wörterbuch ist. Dadurch können Funktionen eine beliebige Anzahl von Argumenten annehmen

Ronak
quelle
17

Für diejenigen unter Ihnen, die anhand von Beispielen lernen!

  1. Der Zweck von * besteht darin, Ihnen die Möglichkeit zu geben, eine Funktion zu definieren, die eine beliebige Anzahl von Argumenten als Liste verwenden kann (z f(*myList). B. ).
  2. Der Zweck von **besteht darin, Ihnen die Möglichkeit zu geben, die Argumente einer Funktion durch Bereitstellung eines Wörterbuchs (z f(**{'x' : 1, 'y' : 2}). B. ) einzugeben .

Lassen Sie uns dies zeigen , indem sie eine Funktion definieren , die zwei normalen Variablen nimmt x, yund kann mehr Argumente als annehmen myArgsund akzeptieren kann noch mehr Argumente als myKW. Später werden wir zeigen , wie zu füttern ymit myArgDict.

def f(x, y, *myArgs, **myKW):
    print("# x      = {}".format(x))
    print("# y      = {}".format(y))
    print("# myArgs = {}".format(myArgs))
    print("# myKW   = {}".format(myKW))
    print("# ----------------------------------------------------------------------")

# Define a list for demonstration purposes
myList    = ["Left", "Right", "Up", "Down"]
# Define a dictionary for demonstration purposes
myDict    = {"Wubba": "lubba", "Dub": "dub"}
# Define a dictionary to feed y
myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"}

# The 1st elem of myList feeds y
f("myEx", *myList, **myDict)
# x      = myEx
# y      = Left
# myArgs = ('Right', 'Up', 'Down')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# y is matched and fed first
# The rest of myArgDict becomes additional arguments feeding myKW
f("myEx", **myArgDict)
# x      = myEx
# y      = Why?
# myArgs = ()
# myKW   = {'y0': 'Why not?', 'q': 'Here is a cue!'}
# ----------------------------------------------------------------------

# The rest of myArgDict becomes additional arguments feeding myArgs
f("myEx", *myArgDict)
# x      = myEx
# y      = y
# myArgs = ('y0', 'q')
# myKW   = {}
# ----------------------------------------------------------------------

# Feed extra arguments manually and append even more from my list
f("myEx", 4, 42, 420, *myList, *myDict, **myDict)
# x      = myEx
# y      = 4
# myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# Without the stars, the entire provided list and dict become x, and y:
f(myList, myDict)
# x      = ['Left', 'Right', 'Up', 'Down']
# y      = {'Wubba': 'lubba', 'Dub': 'dub'}
# myArgs = ()
# myKW   = {}
# ----------------------------------------------------------------------

Vorsichtsmaßnahmen

  1. ** ist ausschließlich Wörterbüchern vorbehalten.
  2. Die nicht optionale Argumentzuweisung erfolgt zuerst.
  3. Sie können ein nicht optionales Argument nicht zweimal verwenden.
  4. Falls zutreffend, **muss *immer danach kommen.
Miladiouss
quelle
14

Aus der Python-Dokumentation:

Wenn mehr Positionsargumente als formale Parameter-Slots vorhanden sind, wird eine TypeError-Ausnahme ausgelöst, es sei denn, ein formaler Parameter mit der Syntax "* identifier" ist vorhanden. In diesem Fall erhält dieser formale Parameter ein Tupel, das die überschüssigen Positionsargumente enthält (oder ein leeres Tupel, wenn keine überschüssigen Positionsargumente vorhanden sind).

Wenn ein Schlüsselwortargument keinem formalen Parameternamen entspricht, wird eine TypeError-Ausnahme ausgelöst, es sei denn, ein formaler Parameter mit der Syntax "** bezeichner" ist vorhanden. In diesem Fall erhält dieser formale Parameter ein Wörterbuch mit den überschüssigen Schlüsselwortargumenten (wobei die Schlüsselwörter als Schlüssel und die Argumentwerte als entsprechende Werte verwendet werden) oder ein (neues) leeres Wörterbuch, wenn keine überschüssigen Schlüsselwortargumente vorhanden sind.

Chris Upchurch
quelle
10

* bedeutet, variable Argumente als Tupel zu erhalten

** bedeutet, variable Argumente als Wörterbuch zu erhalten

Wird wie folgt verwendet:

1) Single *

def foo(*args):
    for arg in args:
        print(arg)

foo("two", 3)

Ausgabe:

two
3

2) Jetzt **

def bar(**kwargs):
    for key in kwargs:
        print(key, kwargs[key])

bar(dic1="two", dic2=3)

Ausgabe:

dic1 two
dic2 3
ishandutta2007
quelle
8

Ich möchte ein Beispiel geben, das andere nicht erwähnt haben

* kann auch einen Generator auspacken

Ein Beispiel aus Python3 Document

x = [1, 2, 3]
y = [4, 5, 6]

unzip_x, unzip_y = zip(*zip(x, y))

unzip_x ist [1, 2, 3], unzip_y ist [4, 5, 6]

Das zip () empfängt mehrere iretable args und gibt einen Generator zurück.

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))
Lochu'an Chang
quelle
7

In Python 3.5, können Sie auch diese Syntax in verwenden list, dict, tuple, und setAnzeigen (manchmal auch als Literale). Siehe PEP 488: Zusätzliche Entpackungsverallgemeinerungen .

>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}

Außerdem können mehrere Iterables in einem einzigen Funktionsaufruf entpackt werden.

>>> range(*[1, 10], *[2])
range(1, 10, 2)

(Danke an mgilson für den PEP-Link.)

leewz
quelle
1
Ich bin mir nicht sicher, ob dies eine Verletzung von "Es gibt nur einen Weg, dies zu tun" ist. Es gibt keine andere Möglichkeit, eine Liste / ein Tupel aus mehreren Iterables zu initialisieren. Derzeit müssen Sie sie zu einem einzigen Iterable verketten, was nicht immer praktisch ist. Sie können über das Rationale in PEP-0448 lesen . Dies ist auch keine python3.x-Funktion, sondern eine python3.5 + -Funktion :-).
mgilson
@mgilson, das würde erklären, warum es vorher nicht erwähnt wurde.
Leewz
6

Zusätzlich zu Funktionsaufrufen sind * args und ** kwargs in Klassenhierarchien nützlich und vermeiden, dass __init__Methoden in Python geschrieben werden müssen. Eine ähnliche Verwendung findet sich in Frameworks wie Django-Code.

Zum Beispiel,

def __init__(self, *args, **kwargs):
    for attribute_name, value in zip(self._expected_attributes, args):
        setattr(self, attribute_name, value)
        if kwargs.has_key(attribute_name):
            kwargs.pop(attribute_name)

    for attribute_name in kwargs.viewkeys():
        setattr(self, attribute_name, kwargs[attribute_name])

Eine Unterklasse kann dann sein

class RetailItem(Item):
    _expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']

class FoodItem(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['expiry_date']

Die Unterklasse wird dann instanziiert als

food_item = FoodItem(name = 'Jam', 
                     price = 12.0, 
                     category = 'Foods', 
                     country_of_origin = 'US', 
                     expiry_date = datetime.datetime.now())

Außerdem kann eine Unterklasse mit einem neuen Attribut, das nur für diese Unterklasseninstanz sinnvoll ist, die Basisklasse aufrufen __init__, um die Attributeinstellung auszulagern. Dies geschieht durch * args und ** kwargs. kwargs werden hauptsächlich verwendet, damit Code mit benannten Argumenten gelesen werden kann. Zum Beispiel,

class ElectronicAccessories(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['specifications']
    # Depend on args and kwargs to populate the data as needed.
    def __init__(self, specifications = None, *args, **kwargs):
        self.specifications = specifications  # Rest of attributes will make sense to parent class.
        super(ElectronicAccessories, self).__init__(*args, **kwargs)

was als ausgelöst werden kann

usb_key = ElectronicAccessories(name = 'Sandisk', 
                                price = '$6.00', 
                                category = 'Electronics',
                                country_of_origin = 'CN',
                                specifications = '4GB USB 2.0/USB 3.0')

Der vollständige Code ist hier

quiet_penguin
quelle
1
1. Grundsätzlich ist init eine Methode, daher ist sie (in diesem Zusammenhang) nicht wirklich anders. 2. Verwenden Sie # für Kommentare, nicht "" ", was nur
Literalzeichenfolgen
4

Aufbauend auf Nickds Antwort ...

def foo(param1, *param2):
    print(param1)
    print(param2)


def bar(param1, **param2):
    print(param1)
    print(param2)


def three_params(param1, *param2, **param3):
    print(param1)
    print(param2)
    print(param3)


foo(1, 2, 3, 4, 5)
print("\n")
bar(1, a=2, b=3)
print("\n")
three_params(1, 2, 3, 4, s=5)

Ausgabe:

1
(2, 3, 4, 5)

1
{'a': 2, 'b': 3}

1
(2, 3, 4)
{'s': 5}

Grundsätzlich kann eine beliebige Anzahl von Positionsargumenten * args verwenden, und alle benannten Argumente (oder kwargs, auch als Schlüsselwortargumente bezeichnet) können ** kwargs verwenden.

Raj
quelle
3

*argsund **kwargs: Sie können eine variable Anzahl von Argumenten an eine Funktion übergeben.

*args: wird verwendet, um eine nicht mit Schlüsselwörtern versehene Argumentliste mit variabler Länge an die Funktion zu senden:

def args(normal_arg, *argv):
    print("normal argument:", normal_arg)

    for arg in argv:
        print("Argument in list of arguments from *argv:", arg)

args('animals', 'fish', 'duck', 'bird')

Wird herstellen:

normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird

**kwargs*

**kwargsMit dieser Option können Sie einer Funktion eine variable Länge von Argumenten mit Schlüsselwörtern übergeben. Sie sollten verwenden, **kwargswenn Sie benannte Argumente in einer Funktion verarbeiten möchten.

def who(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.items():
            print("Your %s is %s." % (key, value))

who(name="Nikola", last_name="Tesla", birthday="7.10.1856", birthplace="Croatia")  

Wird herstellen:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.
Harvey
quelle
2

Dieses Beispiel würde helfen Sie sich daran erinnern *args, **kwargsund auch superund Vererbung in Python auf einmal.

class base(object):
    def __init__(self, base_param):
        self.base_param = base_param


class child1(base): # inherited from base class
    def __init__(self, child_param, *args) # *args for non-keyword args
        self.child_param = child_param
        super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg

class child2(base):
    def __init__(self, child_param, **kwargs):
        self.child_param = child_param
        super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg

c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1
thanhtang
quelle
1

Ein gutes Beispiel für die Verwendung von beiden in einer Funktion ist:

>>> def foo(*arg,**kwargs):
...     print arg
...     print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b) 
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b) 
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}
amir jj
quelle
1

TL; DR

Im Folgenden finden Sie 6 verschiedene Anwendungsfälle für *und **in der Python-Programmierung:

  1. Um eine beliebige Anzahl von Positionsargumenten mit *args: zu akzeptieren def foo(*args): pass, werden hier foobeliebig viele Positionsargumente akzeptiert, dh die folgenden Aufrufe sind gültig foo(1):foo(1, 'bar')
  2. Um eine beliebige Anzahl von Keyword - Argumenten zu akzeptieren **kwargs: def foo(**kwargs): pass , hier ‚foo‘ eine beliebige Anzahl von Keyword - Argumente akzeptiert, dh die folgenden Anrufe gültig foo(name='Tom'),foo(name='Tom', age=33)
  3. Um eine beliebige Anzahl von Positions- und Schlüsselwortargumenten mit *args, **kwargs: zu akzeptieren def foo(*args, **kwargs): pass, werden hier foobeliebig viele Positions- und Schlüsselwortargumente akzeptiert, dh die folgenden Aufrufe sind gültig foo(1,name='Tom'):foo(1, 'bar', name='Tom', age=33)
  4. Um nur Schlüsselwortargumente mit *: zu erzwingen def foo(pos1, pos2, *, kwarg1): pass , *bedeutet dies, dass foo nur Schlüsselwortargumente nach pos2 akzeptiert, daher foo(1, 2, 3)TypeError auslöst, aber in Ordnung foo(1, 2, kwarg1=3)ist.
  5. Um kein weiteres Interesse an mehr Positionsargumenten mit *_(Hinweis: Dies ist nur eine Konvention) auszudrücken : def foo(bar, baz, *_): pass bedeutet (gemäß Konvention) foonur Verwendungen barund bazArgumente in seiner Arbeitsweise und ignoriert andere.
  6. Um kein weiteres Interesse an mehr Schlüsselwortargumenten mit \**_(Hinweis: Dies ist nur eine Konvention) auszudrücken : def foo(bar, baz, **_): pass bedeutet (gemäß Konvention) foonur Verwendungen barund bazArgumente in seiner Arbeitsweise und ignoriert andere.

BONUS: Ab Python 3.8 kann man /in der Funktionsdefinition nur Positionsparameter erzwingen. Im folgenden Beispiel sind die Parameter a und b nur positionell , während c oder d positionell oder Schlüsselwort sein können und e oder f Schlüsselwörter sein müssen:

def f(a, b, /, c, d, *, e, f):
    pass
Meysam Sadeghi
quelle
0

TL; DR

Es packt Argumente für die Funktion in geben listund dictjeweils im Funktionskörper. Wenn Sie eine Funktionssignatur wie folgt definieren:

def func(*args, **kwds):
    # do stuff

Es kann mit einer beliebigen Anzahl von Argumenten und Schlüsselwortargumenten aufgerufen werden. Die Nicht-Schlüsselwort-Argumente werden in eine Liste gepackt, argsdie im Funktionskörper aufgerufen wird, und die Schlüsselwort-Argumente werden in ein Diktat gepackt, kwdsdas im Funktionskörper aufgerufen wird.

func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])

Wenn nun innerhalb des Funktionskörpers die Funktion aufgerufen wird, gibt es zwei lokale Variablen, nämlich argseine Liste mit Wert ["this", "is a list of", "non-keyword", "arguments"]und kwdseine dictmit Wert{"keyword" : "ligma", "options" : [1,2,3]}


Dies funktioniert auch umgekehrt, dh von der Anruferseite. Zum Beispiel, wenn Sie eine Funktion definiert haben als:

def f(a, b, c, d=1, e=10):
    # do stuff

Sie können es aufrufen, indem Sie iterable oder Mappings entpacken, die Sie im aufrufenden Bereich haben:

iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)
RBF06
quelle
0

Kontext

  • Python 3.x.
  • Auspacken mit **
  • Verwendung mit Zeichenfolgenformatierung

Verwendung mit Zeichenfolgenformatierung

Zusätzlich zu den Antworten in diesem Thread gibt es hier ein weiteres Detail, das an keiner anderen Stelle erwähnt wurde. Dies erweitert die Antwort von Brad Solomon

Das Auspacken mit **ist auch nützlich, wenn Sie Python verwendenstr.format .

Dies ist etwas ähnlich wie bei Python- f-strings F-Strings aber mit dem zusätzlichen Aufwand, ein Diktat zu deklarieren, um die Variablen zu halten (F-String erfordert kein Diktat).

Kurzes Beispiel

  ## init vars
  ddvars = dict()
  ddcalc = dict()
  pass
  ddvars['fname']     = 'Huomer'
  ddvars['lname']     = 'Huimpson'
  ddvars['motto']     = 'I love donuts!'
  ddvars['age']       = 33
  pass
  ddcalc['ydiff']     = 5
  ddcalc['ycalc']     = ddvars['age'] + ddcalc['ydiff']
  pass
  vdemo = []

  ## ********************
  ## single unpack supported in py 2.7
  vdemo.append('''
  Hello {fname} {lname}!

  Today you are {age} years old!

  We love your motto "{motto}" and we agree with you!
  '''.format(**ddvars)) 
  pass

  ## ********************
  ## multiple unpack supported in py 3.x
  vdemo.append('''
  Hello {fname} {lname}!

  In {ydiff} years you will be {ycalc} years old!
  '''.format(**ddvars,**ddcalc)) 
  pass

  ## ********************
  print(vdemo[-1])
dreftymac
quelle
-2
  • def foo(param1, *param2):ist eine Methode, die eine beliebige Anzahl von Werten akzeptieren kann für *param2,
  • def bar(param1, **param2): ist eine Methode, die eine beliebige Anzahl von Werten mit Schlüsseln für akzeptieren kann *param2
  • param1 ist ein einfacher Parameter.

Die Syntax zum Implementieren von Varargs in Java lautet beispielsweise wie folgt:

accessModifier methodName(datatype arg) {
    // method body
}
Premraj
quelle