[Edu-sig] Calling functions...
kirby urner
kirby.urner at gmail.com
Sun May 16 03:28:19 CEST 2010
Something I maybe hadn't been clear on
before cramming for a workshop:
Even functions with purely positional
parameters may be passed a dict, in
which case the positional parameters
will be treated like named ones, i.e.
the dict will map to them.
I'll use the new formating protocol:
>>> from __future__ import print_function
>>> def f(a, b, c):
print("a={0}, b={1}, c={2}".format(a,b,c))
>>> f(1,2,3)
a=1, b=2, c=3
Here's what I'm illustrating:
>>> thedict = dict(c=5,a=10,b='cat')
>>> f(**thedict)
a=10, b=cat, c=5
Now what if we try to sneak in an argument
that doesn't map:
>>> thedict = dict(c=5,a=10,b='cat', d='dog')
>>> f(**thedict)
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
f(**thedict)
TypeError: f() got an unexpected keyword argument 'd'
The d is caught, an exception is raised.
So here we might add the all purpose "pooper scooper"
(yeah, scatological -- sometimes effective pedagogy):
>>> def f(a, b, c, **kwargs):
print("a={0}, b={1}, c={2}".format(a,b,c))
The d now gets through, though nothing echoes:
>>> f(**thedict)
a=10, b=cat, c=5
Lets make sure we see what's in "overflow":
>>> def f(a, b, c, **kwargs):
print("a={0}, b={1}, c={2}".format(a,b,c))
print(kwargs)
>>> f(**thedict)
a=10, b=cat, c=5
{'d': 'dog'}
Is an all purpose pooper scooper allowed to have
defaults? No, default arguments are what turn
parameters into named parameters. *args and
**kwargs (often so named by convention) are
not named parameters so much as "collectors"
of "overflow" arguments (made-up terminology).
>>> def f(a, b, c, d='dog', *e):
print("a={0}, b={1}, c={2} d={3} e={4}".format(a,b,c,d,e))
>>> f(**thedict)
a=10, b=cat, c=5 d=dog e=()
>>>
Speaking of made-up terminology, when I pass
**thedict as an argument, I tend to think of the
** as "explode".
If you don't double-star it, it goes through as just
the one argument and an exception gets raised:
>>> f(thedict)
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
f(thedict)
TypeError: f() takes at least 3 arguments (1 given)
The same "explode" operator works for tuples in
that it "unpacks" the one argument into len(tuple)
arguments. The typical use is to make (x,y,z)-tuples
map to some function that expects x, y and z as
separate arguments.
The error messages remind us when we fail to
"explode" one argument into many:
>>> def f(x, y, z):
return x**2 + y**2 + z**2
>>> f(1,2,3)
14
>>> coords = (1,2,3)
>>> f(coords)
Traceback (most recent call last):
File "<pyshell#38>", line 1, in <module>
f(coords)
TypeError: f() takes exactly 3 arguments (1 given)
>>> f(*coords)
14
>>> f(dict(y=2,x=1,z=3))
Traceback (most recent call last):
File "<pyshell#40>", line 1, in <module>
f(dict(y=2,x=1,z=3))
TypeError: f() takes exactly 3 arguments (1 given)
>>> f(**dict(y=2,x=1,z=3))
14
Kirby
More information about the Edu-sig
mailing list