Pass dictionaries in function as arguments
Question:
Im trying to create a function that take unknown number of arguments (dictionaries) to merge them in one. Here is my sketch:
weight = {"sara": 60, "nick": 79, "sem": 78, "ida": 56, "kasia": 58, "slava": 95}
height = { "a" : 1, "b": 2, "c":3 }
width = {"u": "long", "q": 55, "qw": "erre", 30: "34"}
a = {10:20, 20:"a"}
def merge(**dict):
new_dict = {}
for x in dict:
for a, b in x.items():
new_dict[a] = b
return new_dict
print(merge(weight, height, width, a))
And I got error:
TypeError: merge() takes 0 positional arguments but 4 were given
Why?
Answers:
If you want to pass a list
of dict
s as a single argument you have to do this:
def foo(*dicts)
Anyway you SHOULDN’T name it *dict
, since you are overwriting the dict
class.
In Python
you can pass all the arguments as a list
with the *
operator…
def foo(*args)
…and as a dict
with the **
operator
def bar(**kwargs)
For example:
>>> foo(1, 2, 3, 4) # args is accessible as a list [1, 2, 3, 4]
>>> bar(arg1='hello', arg2='world') # kwargs is accessible as a dict {'arg1'='hello', 'arg2'='world'}
In your case you can edit the prototype of you function this way:
def merge(*dicts):
Change def merge(**dict):
to def merge(*dict):
and it is working. Avoid naming it dict
since it is a keyword in python.
First note: dict
is a bad name for an argument as it is already the name of a type.
When you use **
in the argument list for a function it is slurping up any keyword arguments you haven’t explicitly listed. Similarly, a parameter with a single *
is slurping up any extra positional arguments not explicitly named.
Consider:
>>> def foo(bar, **baz): return (bar, baz)
...
>>> foo(42, wooble=42)
(42, {'wooble': 42})
>>> foo(bar=42, wooble=42)
(42, {'wooble': 42})
>>> foo(bar=42, wooble=42, hello="world")
(42, {'wooble': 42, 'hello': 'world'})
>>>
If you wish to take any number of dictionaries as arguments, you’d use:
def merge(*dicts):
...
As dicts
will now slurp up any number of dictionaries passed in.
Im trying to create a function that take unknown number of arguments (dictionaries) to merge them in one. Here is my sketch:
weight = {"sara": 60, "nick": 79, "sem": 78, "ida": 56, "kasia": 58, "slava": 95}
height = { "a" : 1, "b": 2, "c":3 }
width = {"u": "long", "q": 55, "qw": "erre", 30: "34"}
a = {10:20, 20:"a"}
def merge(**dict):
new_dict = {}
for x in dict:
for a, b in x.items():
new_dict[a] = b
return new_dict
print(merge(weight, height, width, a))
And I got error:
TypeError: merge() takes 0 positional arguments but 4 were given
Why?
If you want to pass a list
of dict
s as a single argument you have to do this:
def foo(*dicts)
Anyway you SHOULDN’T name it *dict
, since you are overwriting the dict
class.
In Python
you can pass all the arguments as a list
with the *
operator…
def foo(*args)
…and as a dict
with the **
operator
def bar(**kwargs)
For example:
>>> foo(1, 2, 3, 4) # args is accessible as a list [1, 2, 3, 4]
>>> bar(arg1='hello', arg2='world') # kwargs is accessible as a dict {'arg1'='hello', 'arg2'='world'}
In your case you can edit the prototype of you function this way:
def merge(*dicts):
Change def merge(**dict):
to def merge(*dict):
and it is working. Avoid naming it dict
since it is a keyword in python.
First note: dict
is a bad name for an argument as it is already the name of a type.
When you use **
in the argument list for a function it is slurping up any keyword arguments you haven’t explicitly listed. Similarly, a parameter with a single *
is slurping up any extra positional arguments not explicitly named.
Consider:
>>> def foo(bar, **baz): return (bar, baz)
...
>>> foo(42, wooble=42)
(42, {'wooble': 42})
>>> foo(bar=42, wooble=42)
(42, {'wooble': 42})
>>> foo(bar=42, wooble=42, hello="world")
(42, {'wooble': 42, 'hello': 'world'})
>>>
If you wish to take any number of dictionaries as arguments, you’d use:
def merge(*dicts):
...
As dicts
will now slurp up any number of dictionaries passed in.