Verwendung von *args und **kwargs

Ich habe also Schwierigkeiten mit dem Konzept von "args" und "kwargs".

Bis jetzt habe ich das gelernt:

  • *args = Liste von Argumenten - als positionale Argumente

Ich verstehe nicht, für welche Programmieraufgabe dies hilfreich sein könnte.

Vielleicht:

Ich denke, um Listen und Wörterbücher als Argumente einer Funktion UND gleichzeitig als Platzhalter einzugeben, damit ich JEDES Argument übergeben kann?

Gibt es ein einfaches Beispiel, um zu erklären, wie *args und **kwargs verwendet werden?

Auch das Tutorial, das ich gefunden habe, verwendet nur das "*" und einen Variablennamen.

Sind *args und **kwargs nur Platzhalter oder verwenden Sie genau *args und **kwargs in Ihrem Code?

Lösung

Die Syntax ist die * und **. Die Namen *args und **kwargs sind nur eine Konvention, aber es gibt keine zwingende Notwendigkeit, sie zu verwenden.

Sie würden *args verwenden, wenn Sie nicht sicher sind, wie viele Argumente an Ihre Funktion übergeben werden, d.h. es erlaubt Ihnen, eine beliebige Anzahl von Argumenten an Ihre Funktion zu übergeben. Zum Beispiel:

>>> def print_everything(*args):
        for count, thing in enumerate(args):
...         print( '{0}. {1}'.format(count, thing))
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage

In ähnlicher Weise können Sie mit **kwargs benannte Argumente behandeln, die Sie nicht im Voraus definiert haben:

>>> def table_things(**kwargs):
...     for name, value in kwargs.items():
...         print( '{0} = {1}'.format(name, value))
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit

Sie können diese auch zusammen mit benannten Argumenten verwenden. Die expliziten Argumente erhalten zuerst Werte und dann wird alles andere an *args und **kwargs übergeben. Die benannten Argumente stehen in der Liste an erster Stelle. Zum Beispiel:

def table_things(titlestring, **kwargs)

Sie können auch beide in der gleichen Funktionsdefinition verwenden, aber *args muss vor **kwargs stehen.

Sie können auch die Syntax * und ** verwenden, wenn Sie eine Funktion aufrufen. Zum Beispiel:

>>> def print_three_things(a, b, c):
...     print( 'a = {0}, b = {1}, c = {2}'.format(a,b,c))
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat

Wie Sie sehen können, wird in diesem Fall die Liste (oder das Tupel) von Elementen genommen und entpackt. Auf diese Weise werden sie mit den Argumenten in der Funktion abgeglichen. Natürlich können Sie ein "*" sowohl in der Funktionsdefinition als auch im Funktionsaufruf verwenden.

Kommentare (7)

Ein Ort, an dem die Verwendung von *args und **kwargs sehr nützlich ist, ist die Unterklassenbildung.

class Foo(object):
    def __init__(self, value1, value2):
        # do something with the values
        print value1, value2

class MyFoo(Foo):
    def __init__(self, *args, **kwargs):
        # do something else, don't care about the args
        print 'myfoo'
        super(MyFoo, self).__init__(*args, **kwargs)

Auf diese Weise kann man das Verhalten der Klasse Foo erweitern, ohne viel ueber Foo wissen zu muessen. Das kann sehr praktisch sein, wenn man für eine API programmiert, die sich ändern könnte. MyFoo übergibt einfach alle Argumente an die Foo-Klasse.

Kommentare (8)

Die Namen *args und **kwargs oder **kw sind reine Konvention. Das macht es für uns einfacher, den Code des anderen zu lesen.

Ein Ort, an dem es praktisch ist, ist bei der Verwendung des struct-Moduls

struct.unpack()" gibt ein Tupel zurück, während "struct.pack()" eine variable Anzahl von Argumenten verwendet. Bei der Manipulation von Daten ist es praktisch, ein Tupel an struck.pack() übergeben zu können, z.B.

tuple_of_data = struct.unpack(format_str, data)
... manipulate the data
new_data = struct.pack(format_str, *tuple_of_data)

Ohne diese Möglichkeit wäre man gezwungen, zu schreiben

new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...)

was auch bedeutet, dass ich, wenn sich die format_str ändert und die Größe des Tupels sich ändert, zurückgehen und diese wirklich lange Zeile bearbeiten muss

Kommentare (0)