Explain Codes LogoExplain Codes Logo

Typeerror: got multiple values for argument

python
argument-types
error-prevention
best-practices
Anton ShumikhinbyAnton Shumikhin·Dec 7, 2024
TLDR
# To fix "TypeError: got multiple values for argument": class Demo: def func(self, arg1, arg2): pass demo = Demo() # Wrong: To understand this error, imagine ordering two pizzas, but for the size, # you say "Large" and also whisper "no wait, small". The pizzaiolo would be confused, right? demo.func(1, arg1=2) # TypeError # Right: Here's the correct way, you specify size only once. No more conflicting pizza orders! demo.func(1, arg2=2) # No error

Avoid TypeError by using either positional or keyword for each parameter, not both. This resolves argument conflicts in method calls.

Each Python function has unique expectations for the arguments it should receive. These parameters can be either positional or keyword arguments. When you use both simultaneously, the function might misunderstand what you want (just like the pizzaiolo would).

Argument types: The essential clarification

Python acknowledges two different types of arguments:

  • Positional arguments: They are the "no-nonsense" type. They rely on the order in which they are passed. Just like seating arrangement at a formal dinner.
  • Keyword arguments: They are the "free-spirits". You can place them in any order, given that you specify their name. They're like those friends who sit anywhere at a party.

An important note for keyword arguments: once you start using them in a function call, every argument that follows must be named, or Python will get confused.

Handling variable arguments: No room for TypeError

# Let's deal with flexible numbers of arguments using *args and **kwargs def flexible_func(*args, **kwargs): for arg in args: print(arg) # We're going print crazy here for key, value in kwargs.items(): print(f"{key}: {value}") # Let's print pairs because why not? # Time to call the function flexible_func(1, 2, 3, key1='value1', key2='value2') # Off to the printer they go

The *args and **kwargs idea doesn't involve magic, but rather handling an undefined number of arguments.

Functional Argument Tips: TypeError prevention mode

To avoid the TypeError and make your code less error-prone, here are some simple techniques:

  • Consistency: Stick to one type of argument passing to keep things straightforward.
  • Validate: Check function definitions thoroughly before passing arguments. Especially for functions that aren't straight forward like pandas.set_axis.
  • Comment: Making notes to self is not a sign of old age. It actually makes your code easier to understand.
  • Simplify: Some function calls can be simplified by removing arguments that provide default values. It's like taking off your shoes before entering the house.

Visualization

Let's illustrate the TypeError: got multiple values for argument:

In a Python function call:

order_dish(arg1='Tofu', 'Lentils', arg1='Mushrooms')

Python is confused 🤷‍♂️, it's like giving your waiter different instructions for the same order. The solution is to be clear!

Order like this: Beef Stir-fry with Tofu as arg1 and Lentils as arg2.

Moral: In Python cooking, only give each ingredient once per dish or the chef will throw a TypeError!

Overriding methods with care

If the method in the child class doesn't align with the parent class, Python might respond with: TypeError, I can't let you do that.

class Parent: def method(self, arg1): pass class Child(Parent): # Overriding methods - It's like saying "Sure, I'll follow the recipe, but I like to experiment." # Python isn't a fan of experiments. def method(self, arg1, arg2=None): pass # This will raise a TypeError because it's like trying to fit a square peg in a round hole Parent().method(1, 2)

Decorators have feelings too!

If you're wrapping functions with decorators, you've got to pass the right arguments or Python will get disappointed with you. It's like wrapping presents and forgetting the gift card.

# Decorator that passes all arguments correctly def my_decorator(f): def wrapper(*args, **kwargs): # Likes to dress up before the function call result = f(*args, **kwargs) # Enjoys a bit of comedy after the function call return result return wrapper @my_decorator def say_hello(name): print(f"Hello, {name}") # Decorated function call - it's like having a funny hat, but still doing your job! say_hello("Alice")