TypeError: method() takes 1 positional argument but 2 were given
Solution 1
In Python, this:
my_object.method("foo")
...is syntactic sugar, which the interpreter translates behind the scenes into:
MyClass.method(my_object, "foo")
...which, as you can see, does indeed have two arguments - it's just that the first one is implicit, from the point of view of the caller.
This is because most methods do some work with the object they're called on, so there needs to be some way for that object to be referred to inside the method. By convention, this first argument is called self
inside the method definition:
class MyNewClass:
def method(self, arg):
print(self)
print(arg)
If you call method("foo")
on an instance of MyNewClass
, it works as expected:
>>> my_new_object = MyNewClass()
>>> my_new_object.method("foo")
<__main__.MyNewClass object at 0x29045d0>
foo
Occasionally (but not often), you really don't care about the object that your method is bound to, and in that circumstance, you can decorate the method with the builtin staticmethod()
function to say so:
class MyOtherClass:
@staticmethod
def method(arg):
print(arg)
...in which case you don't need to add a self
argument to the method definition, and it still works:
>>> my_other_object = MyOtherClass()
>>> my_other_object.method("foo")
foo
Solution 2
In simple words.
In Python you should add self
argument as the first argument to all defined methods in classes:
class MyClass:
def method(self, arg):
print(arg)
Then you can use your method according to your intuition:
>>> my_object = MyClass()
>>> my_object.method("foo")
foo
This should solve your problem :)
For a better understanding, you can also read the answers to this question: What is the purpose of self?
Solution 3
Something else to consider when this type of error is encountered:
I was running into this error message and found this post helpful. Turns out in my case I had overridden an __init__()
where there was object inheritance.
The inherited example is rather long, so I'll skip to a more simple example that doesn't use inheritance:
class MyBadInitClass:
def ___init__(self, name):
self.name = name
def name_foo(self, arg):
print(self)
print(arg)
print("My name is", self.name)
class MyNewClass:
def new_foo(self, arg):
print(self)
print(arg)
my_new_object = MyNewClass()
my_new_object.new_foo("NewFoo")
my_bad_init_object = MyBadInitClass(name="Test Name")
my_bad_init_object.name_foo("name foo")
Result is:
<__main__.MyNewClass object at 0x033C48D0>
NewFoo
Traceback (most recent call last):
File "C:/Users/Orange/PycharmProjects/Chapter9/bad_init_example.py", line 41, in <module>
my_bad_init_object = MyBadInitClass(name="Test Name")
TypeError: object() takes no parameters
PyCharm didn't catch this typo. Nor did Notepad++ (other editors/IDE's might).
Granted, this is a "takes no parameters" TypeError, it isn't much different than "got two" when expecting one, in terms of object initialization in Python.
Addressing the topic: An overloading initializer will be used if syntactically correct, but if not it will be ignored and the built-in used instead. The object won't expect/handle this and the error is thrown.
In the case of the sytax error: The fix is simple, just edit the custom init statement:
def __init__(self, name):
self.name = name
Solution 4
Newcomer to Python, I had this issue when I was using the Python's **
feature in a wrong way. Trying to call this definition from somewhere:
def create_properties_frame(self, parent, **kwargs):
using a call without a double star was causing the problem:
self.create_properties_frame(frame, kw_gsp)
TypeError: create_properties_frame() takes 2 positional arguments but 3 were given
The solution is to add **
to the argument:
self.create_properties_frame(frame, **kw_gsp)
Solution 5
As mentioned in other answers - when you use an instance method you need to pass self
as the first argument - this is the source of the error.
With addition to that,it is important to understand that only instance methods take self
as the first argument in order to refer to the instance.
In case the method is Static you don't pass self
, but a cls
argument instead (or class_
).
Please see an example below.
class City:
country = "USA" # This is a class level attribute which will be shared across all instances (and not created PER instance)
def __init__(self, name, location, population):
self.name = name
self.location = location
self.population = population
# This is an instance method which takes self as the first argument to refer to the instance
def print_population(self, some_nice_sentence_prefix):
print(some_nice_sentence_prefix +" In " +self.name + " lives " +self.population + " people!")
# This is a static (class) method which is marked with the @classmethod attribute
# All class methods must take a class argument as first param. The convention is to name is "cls" but class_ is also ok
@classmethod
def change_country(cls, new_country):
cls.country = new_country
Some tests just to make things more clear:
# Populate objects
city1 = City("New York", "East", "18,804,000")
city2 = City("Los Angeles", "West", "10,118,800")
#1) Use the instance method: No need to pass "self" - it is passed as the city1 instance
city1.print_population("Did You Know?") # Prints: Did You Know? In New York lives 18,804,000 people!
#2.A) Use the static method in the object
city2.change_country("Canada")
#2.B) Will be reflected in all objects
print("city1.country=",city1.country) # Prints Canada
print("city2.country=",city2.country) # Prints Canada
Comments
-
Zero Piraeus almost 2 years
If I have a class...
class MyClass: def method(arg): print(arg)
...which I use to create an object...
my_object = MyClass()
...on which I call
method("foo")
like so...>>> my_object.method("foo") Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: method() takes exactly 1 positional argument (2 given)
...why does Python tell me I gave it two arguments, when I only gave one?
-
amoebe almost 7 yearsIn short: Adding
self
as first argument to the method solves the problem. -
abarnert almost 6 yearsThere's no
SyntaxError
here. The code is syntactically correct; it just correctly defines a method named___init__
, which nobody is ever going to call, instead of the special method__init__
. That's why no error is detected—because there isn't one to detect. -
simhumileco over 4 yearsWhat's wrong with this answer? Why did someone give her a negative point? After all, it is the answer to the question and is distinguished by its simplicity compared to other answers, which may be important for some people who are looking for an answer. Isn't it?
-
Little Brain over 4 yearsComing from JavaScript, I expect to be able to pass a list or dictionary as an argument. But it seems like that's not how Python works: you have to destructure the list with * or **, the latter being for a keyworded argument list.
-
smci about 4 years@LittleBrain: yes you can pass a list (or dict) if you want them to be treated as a list (/dict) inside the function. But if you want their individual values unpacked and matched against args (/kwargs) in the function, then you need the
*args
(/**kwargs
) syntax. -
Carlos almost 4 years@amoebe - my type of person
-
efueyo over 3 yearsI'm getting started in OOP and stuck with this example. I will appreciate help to solve it class Catalogo: def __init__(self): self.peliculas = [] def agregar(self, pelicula): self.peliculas.append(pelicula) def mostrar(self): for pelicula in self.peliculas: print(pelicula) # Print toma por defecto str(peicula) pelicula1 = Catalogo ("El Padrino") pelicula2 = Catalogo ("El Padrino: Parte 2") #Catalogo.agregar("El Padrino") #Catalogo.agregar("El Padrino: Parte 2") # Añadimos otra Catalogo.mostrar()
-
Ujjwal over 3 yearsor just adding @staticmethod before defining it. Cool
-
Al Martins about 2 yearsGreat explanation for 'self'
-
Pandiyan Cool about 2 yearsI'm new to python and thanks for this :)
-
grafuls almost 2 yearsIt's wrong to say that you should add
self
argument to ALL defined methods in classes. In the example above there is no use forself
inside the method, therefore it can be decorated with@staticmethod
which in turn wouldn't require you to create an instance of the class. You can read more about it here: docs.python.org/3/library/…