Takes 0 Positional Arguments But 1 Was Given: What It Means and How to Fix It
Getting “takes 0 positional arguments but 1 was given” in Python? This guide explains exactly why it happens and how to fix it, with clear examples for every scenario.
You wrote a function, called it, and Python hit you with: takes 0 positional arguments but 1 was given. The frustrating part is that you might not even be passing any arguments at all. You just called the function normally, and Python is insisting you passed one too many.
This error almost always comes down to how Python handles methods inside classes. Once you understand the mechanics, the fix takes about five seconds. This post walks through every scenario where this error shows up and what to do about each one.
Why This Error Happens
Python passes the instance of a class as the first argument to every method call automatically. That argument is self. When you call my_object.do_something(), Python translates that behind the scenes to MyClass.do_something(my_object).
So if your method isn’t set up to receive self, Python tries to pass the instance in but finds no parameter to put it into. Hence the error: the function takes 0 positional arguments, but Python is sending 1 (the instance itself).
Here’s the simplest version of the problem:
class Calculator:
def add():
return 1 + 1
calc = Calculator()
calc.add()
# TypeError: Calculator.add() takes 0 positional arguments but 1 was given
The method add has no parameters. When you call calc.add(), Python tries to pass calc as the first argument, finds nothing to receive it, and throws the error.
The fix:
class Calculator:
def add(self):
return 1 + 1
Add self as the first parameter. Done.
The Most Common Scenarios
Scenario 1: You Forgot self in a Method Definition
This is the textbook case. You defined a method in a class but left off self:
class Dog:
def bark():
print("Woof!")
rex = Dog()
rex.bark()
# TypeError: Dog.bark() takes 0 positional arguments but 1 was given
Every instance method needs self as its first parameter. It doesn’t have to be named self (Python doesn’t enforce the name), but by convention everyone uses self and you should too:
class Dog:
def bark(self):
print("Woof!")
Scenario 2: You Have a Static Method Without the Decorator
If you want a method that doesn’t use the instance, you have two options: make it a static method or a class method. If you define it without parameters and without the right decorator, you’ll hit this error:
class MathHelper:
def square(n): # Looks like a static method, but isn't decorated
return n * n
helper = MathHelper()
helper.square(4)
# TypeError: MathHelper.square() takes 1 positional argument but 2 were given
Wait, that’s a different error. But call it without arguments and you get the “takes 0 positional arguments but 1 was given” variant. The fix depends on what you actually want:
Option A: Make it a proper static method
class MathHelper:
@staticmethod
def square(n):
return n * n
MathHelper.square(4) # Works fine
helper = MathHelper()
helper.square(4) # Also works fine
Option B: Make it an instance method with self
class MathHelper:
def square(self, n):
return n * n
Use @staticmethod when the method doesn’t need access to the instance or class. Use self when it does.
Scenario 3: You Accidentally Overrode a Built-in Method
This shows up when you’re building a class that extends another and you override a method but mess up the signature:
class MyList(list):
def append(): # Missing self and the item parameter
pass
ml = MyList()
ml.append("hello")
# TypeError: MyList.append() takes 0 positional arguments but 1 was given
Again, self needs to be there, plus any arguments the method is supposed to accept:
class MyList(list):
def append(self, item):
super().append(item)
Scenario 4: Calling the Method From Inside the Class Without self
Sometimes the error fires not when you call the method from outside the class but when one method calls another:
class Processor:
def validate(self, data):
return len(data) > 0
def process(self, data):
if validate(data): # Wrong: should be self.validate(data)
print("Processing...")
Here validate is called as a bare function, not as a method on the instance. Python looks for a function named validate in the local or global scope, not on the class. You’ll get a NameError rather than the positional arguments error in this case, but it’s related enough to mention. The fix is straightforward:
def process(self, data):
if self.validate(data):
print("Processing...")
Always use self.method_name() when calling instance methods from within the class.
Scenario 5: Class Method Missing cls
A similar pattern applies to class methods. These use @classmethod and receive the class itself as the first argument, conventionally named cls:
class Config:
default_timeout = 30
@classmethod
def get_timeout(): # Missing cls
return Config.default_timeout
Config.get_timeout()
# TypeError: Config.get_timeout() takes 0 positional arguments but 1 was given
Fix:
@classmethod
def get_timeout(cls):
return cls.default_timeout
@classmethod methods need cls the same way instance methods need self.
Spotting the Error in Tracebacks
When this error fires in a larger codebase, the traceback helps you locate exactly which method caused it. Look for the line that says TypeError: ClassName.method_name() takes 0 positional arguments but 1 was given.
The class name and method name in that message point you directly to where self or cls is missing. Go to that method definition, check the parameters, and add the missing one.
If the error message says something like takes 1 positional argument but 2 were given, that’s a related issue: the method has self but is being called with one extra argument. Check whether you’re calling it as an instance method when it’s defined as a static method, or passing an explicit argument that shouldn’t be there.
Understanding error messages like this is a core part of writing reliable code. If you’re newer to Python and building these skills, it’s worth reading up on Python programming fundamentals to get a solid grounding in how the language handles objects and methods.
A Side-by-Side Reference
Here’s a quick comparison of the three method types in Python and what their signatures look like:
| Method Type | Decorator | First Parameter | Called On |
|---|---|---|---|
| Instance method | None | self |
Instance |
| Class method | @classmethod |
cls |
Class or instance |
| Static method | @staticmethod |
None (or your own params) | Class or instance |
Getting these confused is the root cause of most “takes 0 positional arguments but 1 was given” errors. When in doubt, ask: does this method need to access instance data? If yes, use self. Does it need to access class-level data but not instance data? Use @classmethod with cls. Does it need neither? Use @staticmethod.
A Real-World Example: Building a Simple Class
Here’s a complete example that covers all three method types correctly, so you can see them working together:
class Temperature:
unit = "Celsius"
def __init__(self, value):
self.value = value
def to_fahrenheit(self): # Instance method
return (self.value * 9/5) + 32
@classmethod
def get_unit(cls): # Class method
return cls.unit
@staticmethod
def is_valid(value): # Static method
return isinstance(value, (int, float))
temp = Temperature(100)
print(temp.to_fahrenheit()) # 212.0
print(Temperature.get_unit()) # Celsius
print(Temperature.is_valid(37)) # True
Each method type has self, cls, or nothing as the first parameter, matching exactly what Python expects.
When You’re Using Frameworks Like Django or Flask
This error also shows up in web frameworks where class-based views are common. In Django, for example, if you define a view method without self or use the wrong number of parameters for a handler, you’ll see this error during a request.
The same rules apply: instance methods need self, and the method signature needs to match what the framework expects to pass in. Checking the framework’s documentation for the correct method signature is the fastest fix in these cases.
Writing clean, testable code in frameworks also connects to good software testing practices, where catching method signature errors early through unit tests saves debugging time later.
Key Takeaways
- The error “takes 0 positional arguments but 1 was given” almost always means a method is missing
selfas its first parameter - Python passes the instance automatically when you call a method on an object, so every instance method needs
selfto receive it - If you don’t need instance data, use
@staticmethodand skipselfentirely - If you need class-level data but not instance data, use
@classmethodwithcls - Class methods that are missing
clstrigger the same error as instance methods missingself - When debugging, read the traceback: the class and method name in the error message point directly to where the fix needs to go
Once you internalize how Python handles self, this error stops being confusing. It’s Python being precise about argument passing, and it’s actually one of the more descriptive error messages the language gives you. Understanding it also deepens your grasp of how object-oriented concepts work in practice, whether you’re writing scripts, building APIs, or working on data pipelines.