-1

I am coding a function as follows:

def create_objection(name, position, **kwargs):
    dicct = {'name':name,
             'position':position}
    print(len(kwargs))
    dicct.update({'extra_info': kwargs})
    return dicct

This function is supposed to get ALWAYS name and position, and eventually a collection of key/value pairs in for or dictionaries. what I want is the following way of working:

create_objection('c1',{'t':1})

Output:

 0
 {'name': 'c1', 'position': {'t': 1}, 'extra_info': {}}

When I try this, then I get an error:

create_objection('c1',{'t':1},{'whatever':[3453,3453]},{'whatever2':[34,34]})

The error:

TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_32291/2973311999.py in <module>
----> 1 create_objection('c1',{'t':1},{'tt':2,'ttt':'3'})

TypeError: create_objection() takes 2 positional arguments but 3 were given

And I would like to get:

{'name': 'c1', 'position': {'t': 1}, 'extra_info': [{'whatever':[3453,3453]},{'whatever2':[34,34]}]}

How to proceed?

Hampus Larsson
  • 3,050
  • 2
  • 14
  • 20
JFerro
  • 3,203
  • 7
  • 35
  • 88
  • 1
    Post the actual whole stack-trace. The problem is most likely spelled out there. The problem is most probably because you've given the function too many positional arguments. the `**kwargs` argument means that it accepts any keyword-elements. – Hampus Larsson Nov 09 '21 at 17:17
  • As said, kwargs is for arguments of type `keyword=value`. It looks like you are using a dictionary as a positional arg. – Seth Faulkner Nov 09 '21 at 17:21
  • d = {'t':1, 'whatever':[3453,3453],'whatever2':[34,34]} def create_objection(*arg, **kwargs): pass create_objection('c', d) – hd1 Nov 09 '21 at 17:22
  • added the error and the results. And more explanation – JFerro Nov 09 '21 at 17:25

3 Answers3

1

What is happening here is that you've defined a function that only has two positional arguments, and you're trying to give it 3, just as the error-message is telling you.

If we look at your code, then it doesn't look like you're trying to use keyword-arguments either so the **kwargs argument doesn't get used.

With just a minor change to your code we can get the result you want:

def create_objection(name, position, *args):
    dicct = {'name': name,
             'position': position}
    if args:
        dicct["extra_info"] = args
    return dicct

x = create_objection('c1', {'t': 1})
z = create_objection('c1', {'t': 1}, {'whatever': [3453, 3453]}, {'whatever2': [34, 34]})

print(x)
print(z)

Output:

{'name': 'c1', 'position': {'t': 1}}
{'name': 'c1', 'position': {'t': 1}, 'extra_info': ({'whatever': [3453, 3453]}, {'whatever2': [34, 34]})}

If you also want to include other keyword-arguments, then you can just do another loop over that variable like so:

def create_objection(name, position, *args, **kwargs):
    dicct = {'name': name,
             'position': position}
    if args:
        dicct["extra_info"] = args
    for key, value in kwargs.items():
        dicct[key] = value
    return dicct

y = create_objection('c1', {'t': 1}, {'whatever': [3453, 3453]}, thisisakeyword="totally a keyword!")
print(y)

Output:

{'name': 'c1', 'position': {'t': 1}, 'extra_info': ({'whatever': [3453, 3453]},), 'thisisakeyword': 'totally a keyword!'}
Hampus Larsson
  • 3,050
  • 2
  • 14
  • 20
0

Try:

def create_objection(*args, **kwargs):
   dicct = {'name': args[0], 'position': args[1]}
   if not kwargs:
       print(len(kwargs))
       dicct.update{{'extra_info': kwargs})
   return dicct

Ignore the above, leaving that for the next lot here, but OP has to change the method to look like:

def create_objection(name=None, position=None, **kwargs):
   dicct = {'name': name, 'position': position}
   if not kwargs:
       print(len(kwargs))
       dicct.update{{'extra_info': kwargs})
   return dicct
hd1
  • 33,938
  • 5
  • 80
  • 91
  • could this approach be expanded to have positional arguments, *args AND **kwargs?? – JFerro Nov 09 '21 at 17:28
  • *args is a list, **kwargs is a dict. As this solves your immediate problem, use it and post another question for your next issue – hd1 Nov 09 '21 at 17:29
  • the down side of this is that I can not call the method with objection=create_objection(name='XY', position='pos3') – JFerro Nov 09 '21 at 17:36
  • See the text I appended to my answer – hd1 Nov 09 '21 at 18:08
0

Here is a similar issue

It looks like you need to unpack your dictionary when calling your function.

create_objection('c1',{'t':1},**{'whatever':[3453,3453]},{'whatever2':[34,34]})

Note the **

Seth Faulkner
  • 461
  • 1
  • 5
  • 16