Python method takes one positional argument, but two are given
I came across an error that I don't quite understand. If I have the following snippet:
class Test(object):
def __init__(self):
self.data = {}
def update_data(self, **update):
self.data = update
t = Test()
t.update_data(test='data') # Works
t.update_data({'test':'data'}) # TypeError: update_data() takes 1 positional argument but 2 were given
So from what I understand, the syntax **update
is dictionary destruction syntax and when you pass a dict to a function it gets converted to keyword arguments.
What am I misunderstanding here?
source to share
If you just go to the dictionary, it will be treated like any other variable. In your case, you passed it as a positional argument, so it will be treated as a positional argument. However, the method does not take any positional arguments (other than self
, and another history), so it throws an error.
If you want to pass the contents of the dictionary as keyword arguments, you need to unpack it ( **
before the dictionary):
t.update_data(**{'test':'data'})
If you want to go into a dictionary like a dictionary, you can also pass it as a keyword argument (no unpacking!):
t.update_data(funkw={'test':'data'})
source to share
When you pass the function keyword arguments, it is converted to a dictionary. Not the other way around.
Detailed explanation of arguments and kwargs
* args means the function / method can take any number of positional arguments and will be stored in a list called args.
** kwargs means it can take any number of named arguments and will be stored in the cwargs dictionary Still unclear? Let me give you an example (albeit very simple and naive) -
# Suppose you want to write a function that can find the
# sum of all the numbers passed to it.
def sum(a, b):
return a + b
>>> sum(2, 3) # => 5
# Now this function can only find sum of two numbers, what
# if we have 3, 4 or more numbers, how would be go solving that.
# Easy let take an array/list as an argument -
def sum(numbers):
total = 0
for number in numbers:
total += number
return total
# But now we'd have to call it like -
>>> sum([2, 3]) # => 5
>>> sum(2, 3) # => throws an error.
# That might be ok for some other programming languages, but not
# for Python. So python allows you to pass any number of
# arguments, and it would automatically store them into list
# called args (as a conventions, but it can be called
# anything else say 'numbers')
def sum(*numbers):
total = 0
for number in numbers:
total += number
return total
>>> sum(2, 3, 4) # => 9
# Viola!
Likewise, kwargs are used to automatically save all named arguments as a dictionary.
source to share