Skip to content

Fix: Python TypeError: takes X positional arguments but Y were given

FixDevs ·

Quick Answer

How to fix Python TypeError takes positional arguments but were given caused by missing self, extra arguments, wrong function calls, and class method confusion.

The Error

You call a function or method and get:

TypeError: greet() takes 1 positional argument but 2 were given

Or variations:

TypeError: __init__() takes 1 positional argument but 2 were given
TypeError: process() takes 2 positional arguments but 3 were given
TypeError: calculate() takes 0 positional arguments but 1 was given

Python received more arguments than the function is defined to accept. The numbers in the error tell you exactly what happened — the function expected X arguments but got Y.

Why This Happens

The most confusing version is takes 1 positional argument but 2 were given when you only passed 1 argument. The hidden extra argument is self. When you call instance.method(arg), Python implicitly passes instance as self, making it 2 arguments total.

Common causes:

  • Forgot self in method definition. The method does not declare self as its first parameter.
  • Called an instance method on the class. MyClass.method(arg) passes arg as self.
  • Passed too many arguments. The function simply does not accept that many.
  • Decorator changed the signature. A decorator consumed or added arguments.
  • Confused a function with a method. Passing self explicitly when it should be implicit.

Fix 1: Add self to Instance Methods

The most common cause. If you define a method inside a class without self, calling it on an instance passes the instance as the first argument, shifting everything:

Broken:

class Calculator:
    def add(a, b):  # Missing self!
        return a + b

calc = Calculator()
calc.add(2, 3)
# TypeError: add() takes 2 positional arguments but 3 were given
# Python sent: add(calc, 2, 3) — 3 arguments, not 2

Fixed:

class Calculator:
    def add(self, a, b):
        return a + b

calc = Calculator()
calc.add(2, 3)  # Works — Python sends add(calc, 2, 3)

Every instance method must have self as its first parameter. Python passes the instance automatically.

Pro Tip: If the method does not need access to self (no instance state), use @staticmethod:

class Calculator:
    @staticmethod
    def add(a, b):
        return a + b

Calculator.add(2, 3)  # Works without self

Fix 2: Fix init Argument Count

A common variant when creating class instances:

Broken:

class User:
    def __init__(self):  # Only accepts self
        pass

user = User("Alice")
# TypeError: __init__() takes 1 positional argument but 2 were given

Fixed — add the parameter:

class User:
    def __init__(self, name):
        self.name = name

user = User("Alice")  # Works

Or accept optional arguments:

class User:
    def __init__(self, name="Anonymous"):
        self.name = name

User()          # Works — name defaults to "Anonymous"
User("Alice")   # Works

Fix 3: Fix Extra Arguments

You might be passing more arguments than the function accepts:

def greet(name):
    print(f"Hello, {name}!")

greet("Alice", "Bob")
# TypeError: greet() takes 1 positional argument but 2 were given

Fix: Check the function signature:

import inspect
print(inspect.signature(greet))
# (name)

Either pass fewer arguments or update the function to accept more:

def greet(name, *others):
    print(f"Hello, {name}!")
    for other in others:
        print(f"Hello, {other}!")

greet("Alice", "Bob")  # Works

Fix 4: Fix Callback Argument Mismatches

When using callbacks with map, filter, sorted, or event handlers, the caller determines how many arguments your function receives:

Broken:

names = ["Alice", "Bob", "Charlie"]

def format_name(name, index):
    return f"{index}: {name}"

list(map(format_name, names))
# TypeError: format_name() missing 1 required positional argument: 'index'

map() passes one argument per iterable. To get the index too:

Fixed:

list(map(format_name, names, range(len(names))))
# Or better:
[f"{i}: {name}" for i, name in enumerate(names)]

Broken with sorted:

def compare(a, b):
    return len(a) - len(b)

sorted(names, key=compare)
# TypeError: compare() takes 2 positional arguments but 1 was given

sorted(key=...) passes one argument to the key function, not two:

Fixed:

sorted(names, key=len)
# Or:
sorted(names, key=lambda name: len(name))

For the inverse error (missing required arguments), see Fix: Python TypeError: missing required positional argument.

Fix 5: Fix Property Decorator Issues

If you accidentally call a property like a regular method:

class User:
    @property
    def name(self):
        return self._name

user = User()
user.name()  # TypeError: 'str' object is not callable

Properties are accessed without parentheses: user.name, not user.name().

The reverse problem — defining a method but accessing it as a property:

class User:
    def get_name(self):
        return self._name

user = User()
print(user.get_name)  # Prints the method object, not the name
print(user.get_name())  # Correct — calls the method

Fix 6: Fix Class Method vs Static Method

@classmethod receives cls as the first argument:

class User:
    count = 0

    @classmethod
    def create(cls, name):
        cls.count += 1
        return cls(name)

@staticmethod receives no implicit arguments:

class MathUtils:
    @staticmethod
    def add(a, b):
        return a + b

Common mistake — using @classmethod but forgetting cls:

class Config:
    @classmethod
    def from_file(path):  # Missing cls!
        pass

Config.from_file("config.yaml")
# TypeError: from_file() takes 1 positional argument but 2 were given

Fixed:

class Config:
    @classmethod
    def from_file(cls, path):
        return cls()

Fix 7: Fix *args and **kwargs

Use *args to accept any number of positional arguments:

def log(*messages):
    for msg in messages:
        print(msg)

log("hello")                    # 1 argument — works
log("hello", "world", "!")      # 3 arguments — works

Use **kwargs for keyword arguments:

def create_user(**kwargs):
    print(kwargs)

create_user(name="Alice", age=30)
# {'name': 'Alice', 'age': 30}

Combine both:

def flexible(required, *args, **kwargs):
    print(f"Required: {required}")
    print(f"Extra positional: {args}")
    print(f"Keyword: {kwargs}")

flexible("hello", 1, 2, 3, debug=True)

Common Mistake: Passing a list as a single argument when you meant to unpack it:

def add(a, b, c):
    return a + b + c

numbers = [1, 2, 3]
add(numbers)     # TypeError: takes 3 but 1 given
add(*numbers)    # Works — unpacks to add(1, 2, 3)

Fix 8: Debug the Error

When the error is unclear, inspect the call:

import inspect

# Check the expected signature
print(inspect.signature(my_function))

# Check all parameters
for name, param in inspect.signature(my_function).parameters.items():
    print(f"  {name}: kind={param.kind.name}, default={param.default}")

Count the arguments manually:

def process(self, data, format, verbose=False):
    pass

# instance.process(data, "json", True)
# Python sends: process(instance, data, "json", True) = 4 arguments
# Signature expects: self, data, format, verbose = 4 parameters ✓

Remember that self and cls count as arguments. Python reports the total including these implicit arguments.

Still Not Working?

Check for metaclasses. Custom metaclasses can change how __init__ and __new__ work, altering the expected argument count.

Check for __call__. If an object implements __call__, calling it like a function passes arguments to __call__, which needs self:

class Multiplier:
    def __init__(self, factor):
        self.factor = factor

    def __call__(self, value):  # Needs self!
        return value * self.factor

double = Multiplier(2)
double(5)  # 10 — calls __call__(self, 5)

Check for circular imports. A circular import might cause a class to be partially loaded, making methods unavailable. See Fix: Python ImportError: circular import.

Check for name shadowing. A local variable might shadow the function you intend to call:

len = 5  # Shadows the built-in len()
len([1, 2, 3])  # TypeError: 'int' object is not callable

If the error involves None instead of too many arguments, see Fix: TypeError: ‘NoneType’ object is not subscriptable.

For the missing self version of this error in Python, see Fix: Python command not found if Python itself is not running.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles