Introduction
This section covers variadic function arguments, sometimes described as *args
and **kwargs
.
This tutorial is from open-source community. Access the source code
This section covers variadic function arguments, sometimes described as *args
and **kwargs
.
A function that accepts any number of arguments is said to use variable arguments. For example:
def f(x, *args):
...
Function call.
f(1,2,3,4,5)
The extra arguments get passed as a tuple.
def f(x, *args):
## x -> 1
## args -> (2,3,4,5)
A function can also accept any number of keyword arguments. For example:
def f(x, y, **kwargs):
...
Function call.
f(2, 3, flag=True, mode='fast', header='debug')
The extra keywords are passed in a dictionary.
def f(x, y, **kwargs):
## x -> 2
## y -> 3
## kwargs -> { 'flag': True, 'mode': 'fast', 'header': 'debug' }
A function can also accept any number of variable keyword and non-keyword arguments.
def f(*args, **kwargs):
...
Function call.
f(2, 3, flag=True, mode='fast', header='debug')
The arguments are separated into positional and keyword components
def f(*args, **kwargs):
## args = (2, 3)
## kwargs -> { 'flag': True, 'mode': 'fast', 'header': 'debug' }
...
This function takes any combination of positional or keyword arguments. It is sometimes used when writing wrappers or when you want to pass arguments through to another function.
Tuples can be expanded into variable arguments.
numbers = (2,3,4)
f(1, *numbers) ## Same as f(1,2,3,4)
Dictionaries can also be expanded into keyword arguments.
options = {
'color' : 'red',
'delimiter' : ',',
'width' : 400
}
f(data, **options)
## Same as f(data, color='red', delimiter=',', width=400)
Try defining the following function:
>>> 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
>>>
Notice how the parameter *more
collects all of the extra arguments.
Suppose you read some data from a file and obtained a tuple such as this:
>>> data = ('GOOG', 100, 490.1)
>>>
Now, suppose you wanted to create a Stock
object from this data. If you try to pass data
directly, it doesn't work:
>>> 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'
>>>
This is easily fixed using *data
instead. Try this:
>>> s = Stock(*data)
>>> s
Stock('GOOG', 100, 490.1)
>>>
If you have a dictionary, you can use **
instead. For example:
>>> data = { 'name': 'GOOG', 'shares': 100, 'price': 490.1 }
>>> s = Stock(**data)
Stock('GOOG', 100, 490.1)
>>>
In your report.py
program, you created a list of instances using code like this:
def read_portfolio(filename):
'''
Read a stock portfolio file into a list of dictionaries with keys
name, shares, and price.
'''
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)
You can simplify that code using Stock(**d)
instead. Make that change.
The fileparse.parse_csv()
function has some options for changing the file delimiter and for error reporting. Maybe you'd like to expose those options to the read_portfolio()
function above. Make this change:
def read_portfolio(filename, **opts):
'''
Read a stock portfolio file into a list of dictionaries with keys
name, shares, and price.
'''
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)
Once you've made the change, trying reading a file with some errors:
>>> import report
>>> port = report.read_portfolio('missing.csv')
Row 4: Couldn't convert ['MSFT', '', '51.23']
Row 4: Reason invalid literal for int() with base 10: ''
Row 7: Couldn't convert ['IBM', '', '70.44']
Row 7: Reason invalid literal for int() with base 10: ''
>>>
Now, try silencing the errors:
>>> import report
>>> port = report.read_portfolio('missing.csv', silence_errors=True)
>>>
Congratulations! You have completed the Variable Arguments lab. You can practice more labs in LabEx to improve your skills.