[Tutor] the "**" operator?

Alex Hall mehgcap at gmail.com
Sat Dec 11 01:26:52 CET 2010

```Thanks all! I thought update() would add an item even if it would be a
duplicate, but apparently not. I also now better understand why I am
always passing around *args and **kwargs when calling super(). Very
interesting...

On 12/10/10, Hugo Arts <hugo.yoshi at gmail.com> wrote:
> On Fri, Dec 10, 2010 at 8:14 PM, Alex Hall <mehgcap at gmail.com> wrote:
>> Hi all,
>> I was googling a way to do something like
>>
>
>
> http://docs.python.org/library/stdtypes.html#dict.update
>
>> and someone on a forum recommends this:
>> What is the ** doing here? I tried to look it up, but Google seems to
>> ignore it since it is punctuation. The poster on the forum says it
>> will put all elements of additionaldict in mydict that are not already
>> in mydict, which is the behavior I am looking for, but I am not sure
>> why this would be so. TIA.
>>
>
> The * and **, when calling functions, are what's called extended
> calling syntax. It's a bit hard to explain, so I'm going to do a sort
> of clarify by example here:
>
>>>> def f(a, b, c):
> ...     print a, b, c
> ...
>>>> f(1, 2, 3)
> 1 2 3
>>>> a = [1, 2, 3]
>>>> f(*a)
> 1 2 3
>>>> b = {'a': 2, 'b': 1, 'c': 3}
>>>> f(*b)
> a c b
>>>> f(**b)
> 2 1 3
>
> In short, if a = [1, 2, 3], f(*a) is the same as f(1, 2, 3). if b =
> {'a': 2, 'b': 1, 'c': 3}, then f(**b) is the same as f(a=2, b=1, c=3).
>
> The * will iterate over its argument, and supply the resulting values
> as arguments to the function (iterating over a dict will return its
> keys, which is what you see with f(*b) here). ** requires a mapping
> type, and supplies the keys and values to the function as keyword
> arguments.
>
> * and ** are very flexible, and you can use them alongside with
> regular arguments:
>
>>>> f(1, *[2, 3])
> 1 2 3
>>>> f(1, **{'b': 2, 'c': 3})
> 1 2 3
>
> * and ** also have uses in function definition, where they sort of do
> the reverse. They can capture any number of regular or keyword
> arguments in a tuple or dictionary:
>
>>>> def f(*args, **kwargs):
> ...     print args, kwargs
> ...
>>>> f()
> () {}
>>>> f(1, 2, 3)
> (1, 2, 3) {}
>>>> f(1, 2, 3, a=4, b=5)
> (1, 2, 3) {'a': 4, 'b': 5}
>>>> f(a=4, b=5)
> () {'a': 4, 'b': 5}
>
> Like with function calls, you can mix up regular arguments and */**
> arguments, as long as the resulting function is unambiguous:
>
>>>> def f(a, *args, **kwargs):
> ...     print a, args, kwargs
> ...
>>>> f()
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: f() takes at least 1 argument (0 given)
>>>> f(1)
> 1 () {}
>>>> f(1, 2, 3)
> 1 (2, 3) {}
>>>> f(1, 2, 3, b=4, c=5)
> 1 (2, 3) {'c': 5, 'b': 4}
>

--
Have a great day,
Alex (msg sent from GMail website)
mehgcap at gmail.com; http://www.facebook.com/mehgcap
```