Variadische Funktionsargumente in Python

Beginner

This tutorial is from open-source community. Access the source code

Einführung

Dieser Abschnitt behandelt variadische Funktionsargumente, die manchmal als *args und **kwargs beschrieben werden.

Positionalvariable Argumente (*args)

Eine Funktion, die eine beliebige Anzahl von Argumenten akzeptiert, wird als Funktion mit variablen Argumenten bezeichnet. Beispielsweise:

def f(x, *args):
 ...

Funktionsaufruf:

f(1,2,3,4,5)

Die zusätzlichen Argumente werden als Tupel übergeben.

def f(x, *args):
    ## x -> 1
    ## args -> (2,3,4,5)

Schlüsselwortvariable Argumente (**kwargs)

Eine Funktion kann auch eine beliebige Anzahl von Schlüsselwortargumenten akzeptieren. Beispielsweise:

def f(x, y, **kwargs):
...

Funktionsaufruf:

f(2, 3, flag=True, mode='fast', header='debug')

Die zusätzlichen Schlüsselwörter werden in einem Wörterbuch übergeben.

def f(x, y, **kwargs):
    ## x -> 2
    ## y -> 3
    ## kwargs -> { 'flag': True,'mode': 'fast', 'header': 'debug' }

Kombinieren beider

Eine Funktion kann auch eine beliebige Anzahl von variablen Schlüsselwort- und Nicht-Schlüsselwortargumenten akzeptieren.

def f(*args, **kwargs):
...

Funktionsaufruf:

f(2, 3, flag=True, mode='fast', header='debug')

Die Argumente werden in positionale und Schlüsselwortkomponenten getrennt:

def f(*args, **kwargs):
    ## args = (2, 3)
    ## kwargs -> { 'flag': True,'mode': 'fast', 'header': 'debug' }
...

Diese Funktion nimmt beliebige Kombinationen von positionellen oder Schlüsselwortargumenten entgegen. Sie wird manchmal verwendet, wenn Wrapper geschrieben werden oder wenn Sie Argumente an eine andere Funktion weiterleiten möchten.

Übergabe von Tupeln und Wörterbüchern

Tupel können in variable Argumente erweitert werden.

numbers = (2,3,4)
f(1, *numbers)      ## Entspricht f(1,2,3,4)

Wörterbücher können auch in Schlüsselwortargumente erweitert werden.

options = {
    'color' : 'rot',
    'delimiter' : ',',
    'width' : 400
}
f(data, **options)
## Entspricht f(data, color='rot', delimiter=',', width=400)

Übung 7.1: Ein einfaches Beispiel mit variablen Argumenten

Versuchen Sie, die folgende Funktion zu definieren:

>>> def avg(x,*more):
        return float(x+sum(more))/(1+len(more))

>>> avg(10,11)
10.5
>>> avg(3,4,5)
4.0
>>> avg(1,2,3,4,5,6)
3.5
>>>

Bemerken Sie, wie der Parameter *more alle zusätzlichen Argumente sammelt.

Übung 7.2: Übergabe von Tupeln und Wörterbüchern als Argumente

Nehmen wir an, Sie lesen einige Daten aus einer Datei und erhalten ein Tupel wie dieses:

>>> data = ('GOOG', 100, 490.1)
>>>

Nun, nehmen wir an, Sie möchten ein Stock-Objekt aus diesen Daten erstellen. Wenn Sie versuchen, data direkt zu übergeben, funktioniert das nicht:

>>> from stock import Stock
>>> s = Stock(data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Stock.__init__() missing 2 required positional arguments:'shares' and 'price'
>>>

Dies lässt sich leicht beheben, indem Sie *data verwenden. Probieren Sie das:

>>> s = Stock(*data)
>>> s
Stock('GOOG', 100, 490.1)
>>>

Wenn Sie ein Wörterbuch haben, können Sie stattdessen ** verwenden. Beispielsweise:

>>> data = { 'name': 'GOOG','shares': 100, 'price': 490.1 }
>>> s = Stock(**data)
Stock('GOOG', 100, 490.1)
>>>

Übung 7.3: Erstellen einer Liste von Instanzen

In Ihrem report.py-Programm haben Sie eine Liste von Instanzen mit Code wie diesem erstellt:

def read_portfolio(filename):
    '''
    Liest eine Datei mit einem Aktienportfolio in eine Liste von Wörterbüchern mit den Schlüsseln
    name, shares und price ein.
    '''
    with open(filename) as lines:
        portdicts = fileparse.parse_csv(lines,
                               select=['name','shares','price'],
                               types=[str,int,float])

    portfolio = [ Stock(d['name'], d['shares'], d['price'])
                  for d in portdicts ]
    return Portfolio(portfolio)

Sie können diesen Code vereinfachen, indem Sie Stock(**d) verwenden. Machen Sie diese Änderung.

Übung 7.4: Argumentweiterleitung

Die fileparse.parse_csv()-Funktion hat einige Optionen zur Änderung des Dateiteilnehmers und zur Fehlerberichterstattung. Vielleicht möchten Sie diese Optionen der obigen read_portfolio()-Funktion zur Verfügung stellen. Machen Sie diese Änderung:

def read_portfolio(filename, **opts):
    '''
    Liest eine Datei mit einem Aktienportfolio in eine Liste von Wörterbüchern mit den Schlüsseln
    name, shares und price ein.
    '''
    with open(filename) as lines:
        portdicts = fileparse.parse_csv(lines,
                                        select=['name','shares','price'],
                                        types=[str,int,float],
                                        **opts)

    portfolio = [ Stock(**d) for d in portdicts ]
    return Portfolio(portfolio)

Sobald Sie die Änderung vorgenommen haben, versuchen Sie, eine Datei mit einigen Fehlern zu lesen:

>>> import report
>>> port = report.read_portfolio('missing.csv')
Zeile 4: Konvertierung von ['MSFT', '', '51.23'] fehlgeschlagen
Zeile 4: Grund ungültiger Buchstabe für int() mit Basis 10: ''
Zeile 7: Konvertierung von ['IBM', '', '70.44'] fehlgeschlagen
Zeile 7: Grund ungültiger Buchstabe für int() mit Basis 10: ''
>>>

Jetzt versuchen Sie, die Fehler zu unterdrücken:

>>> import report
>>> port = report.read_portfolio('missing.csv', silence_errors=True)
>>>

Zusammenfassung

Herzlichen Glückwunsch! Sie haben das Lab zu Variablen Argumenten abgeschlossen. Sie können in LabEx weitere Labs absolvieren, um Ihre Fähigkeiten zu verbessern.