Pireo cero
Si tengo una clase…
class MyClass:
def method(arg):
print(arg)
… que uso para crear un objeto …
my_object = MyClass()
… en el que llamo method("foo")
al igual que …
>>> my_object.method("foo")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: method() takes exactly 1 positional argument (2 given)
… ¿por qué Python me dice que le di dos argumentos, cuando solo le di uno?
Pireo cero
En Python, esto:
my_object.method("foo")
… es azúcar sintácticaque la intérprete traduce tras bambalinas en:
MyClass.method(my_object, "foo")
… que, como puede ver, de hecho tiene dos argumentos: es solo que el primero está implícito, desde el punto de vista de la persona que llama.
Esto se debe a que la mayoría de los métodos funcionan con el objeto al que se llaman, por lo que debe haber alguna forma de hacer referencia a ese objeto dentro del método. Por convención, este primer argumento se llama self
dentro de la definición del método:
class MyNewClass:
def method(self, arg):
print(self)
print(arg)
si llamas method("foo")
en una instancia de MyNewClass
funciona como se esperaba:
>>> my_new_object = MyNewClass()
>>> my_new_object.method("foo")
<__main__.MyNewClass object at 0x29045d0>
foo
De vez en cuando (pero no a menudo), realmente no preocuparse por el objeto al que está vinculado su método, y en esa circunstancia, puede Decorar el método con el incorporado staticmethod()
función para decirlo:
class MyOtherClass:
@staticmethod
def method(arg):
print(arg)
… en cuyo caso no es necesario agregar un self
argumento a la definición del método, y todavía funciona:
>>> my_other_object = MyOtherClass()
>>> my_other_object.method("foo")
foo
-
En resumen: agregar
self
como primer argumento del método resuelve el problema.– amebe
10 de junio de 2017 a las 11:15
-
o simplemente agregando @staticmethod antes de definirlo. Fresco
– Ujjwal
6 de septiembre de 2020 a las 6:38
simhumileco
En palabras simples
En Python debes agregar self
como primer parámetro para todos los métodos definidos en las clases:
class MyClass:
def method(self, arg):
print(arg)
Entonces puedes usar tu método de acuerdo a tu intuición:
>>> my_object = MyClass()
>>> my_object.method("foo")
foo
Para una mejor comprensión, también puede leer las respuestas a esta pregunta: ¿Cuál es el propósito de uno mismo?
-
¿Qué tiene de malo esta respuesta? ¿Por qué alguien le dio un punto negativo? Después de todo, es la respuesta a la pregunta y se distingue por su simplicidad en comparación con otras respuestas, lo que puede ser importante para algunas personas que buscan una respuesta. ¿no es así?
– simhumileco
8 de agosto de 2019 a las 21:53
-
Está mal decir que debes agregar
self
argumento a TODO métodos definidos en las clases. En el ejemplo anterior no hay uso paraself
dentro del método, por lo tanto se puede decorar con@staticmethod
lo que a su vez no requeriría que cree una instancia de la clase. Puedes leer más sobre esto aquí: docs.python.org/3/library/…– grafuls
27 mayo 2022 a las 12:30
-
También es posible tener
@classmethod
sque tomancls
como su primer parámetro, noself
.– wjandrea
15 de noviembre de 2022 a las 18:16
jonru
Algo más a considerar cuando se encuentra este tipo de error:
Me encontré con este mensaje de error y encontré útil esta publicación. Resulta que en mi caso había anulado un __init__()
donde había herencia de objetos.
El ejemplo heredado es bastante largo, así que pasaré a un ejemplo más simple que no usa la herencia:
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")
El resultado es:
<__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 no detectó este error tipográfico. Notepad++ tampoco (otros editores/IDE podrían).
Por supuesto, este es un TypeError “no toma parámetros”, no es muy diferente de “obtuve dos” cuando esperaba uno, en términos de inicialización de objetos en Python.
Abordar el tema: se usará un inicializador de sobrecarga si es sintácticamente correcto, pero si no, se ignorará y se usará el integrado en su lugar. El objeto no espera/maneja esto y se lanza el error.
En el caso del error de sytax: la solución es simple, simplemente edite la declaración de inicio personalizada:
def __init__(self, name):
self.name = name
-
No hay
SyntaxError
aquí. El código es sintácticamente correcto; simplemente define correctamente un método llamado___init__
que nadie va a llamar nunca, en lugar del método especial__init__
. Por eso no se detecta ningún error, porque no hay ninguno que detectar.– abarnert
27 de junio de 2018 a las 21:29
-
A mi me paso exactamente lo mismo pero con
__int__(self, ...):
. Horas perdidas por ese error tipográfico.– anónimo
5 sep 2022 a las 20:02
-
Me alegra que haya encontrado una solución, pero este es un problema totalmente diferente al de la pregunta. Diría que podría publicar su propia pregunta, pero ya se ha publicado el mismo tipo de cosas, por ejemplo: error “Este constructor no acepta argumentos” en
__init__
(el error fue_init_
).– wjandrea
15 de noviembre de 2022 a las 18:36
Stanislav Pankévich
Este problema también puede deberse a que no se pasan correctamente los argumentos de palabras clave a una función.
Por ejemplo, dado un método definido como:
def create_properties_frame(self, parent, **kwargs):
una llamada como esta:
self.create_properties_frame(frame, kw_gsp)
causará TypeError: create_properties_frame() takes 2 positional arguments but 3 were given
porque el kw_gsp
el diccionario se trata como un argumento posicional en lugar de descomprimirse en argumentos de palabras clave separados.
La solución es agregar **
al argumento:
self.create_properties_frame(frame, **kw_gsp)
RtmA
Como se menciona en otras respuestas, cuando usa un método de instancia, debe pasar self
como primer argumento: esta es la fuente del error.
Además de eso, es importante entender que solo los métodos de instancia toman self
como primer argumento para referirse a la instancia.
En caso de que el método sea Estático tu no pasas self
pero un cls
argumento en su lugar (o class_
).
Por favor, vea un ejemplo a continuación.
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
Algunas pruebas solo para dejar las cosas más claras:
# 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
-
Esta terminología es incorrecta.
classmethod
s ystaticmethod
s son dos cosas diferentes.classmethod
apostarcls
mientrasstaticmethod
s no tiene ningún parámetro requerido.– wjandrea
15 de noviembre de 2022 a las 18:25
-
Además, no creo que este sea un buen ejemplo de un
classmethod
porque para que querrías unoCity
ejemplo para afectar a todos los demás? Como, ¿por qué elCity
clase incluso tiene uncountry
atributo en primer lugar? ¿No debería cada unoCity
instancia definir su propio país? Di que quería hacer unCity
instancia para Tokio y otra para Toronto; eso no es posible con esto, entonces, ¿cómo es útil? He aquí un mejor ejemplo, incluyendo unstaticmethod
.– wjandrea
15 de noviembre de 2022 a las 18:28
-
Gracias @wjandrea, no estoy 100% seguro de haber entendido tus comentarios y por qué mi respuesta está dando información incorrecta de alguna manera.
– RtmY
15/11/2022 a las 19:35
andrea
Ocurre cuando no especificas el número de parámetros que __init__()
o cualquier otro método buscando.
Por ejemplo:
class Dog:
def __init__(self):
print("IN INIT METHOD")
def __unicode__(self,):
print("IN UNICODE METHOD")
def __str__(self):
print("IN STR METHOD")
obj = Dog("JIMMY", 1, 2, 3, "WOOF")
Cuando ejecuta el programa anterior, le da un error como ese:
TypeError: __init__() takes 1 positional argument but 6 were given
¿Cómo podemos deshacernos de esta cosa?
Solo pasa los parametros, que __init__()
método buscando
class Dog:
def __init__(self, dogname, dob_d, dob_m, dob_y, dogSpeakText):
self.name_of_dog = dogname
self.date_of_birth = dob_d
self.month_of_birth = dob_m
self.year_of_birth = dob_y
self.sound_it_make = dogSpeakText
def __unicode__(self, ):
print("IN UNICODE METHOD")
def __str__(self):
print("IN STR METHOD")
obj = Dog("JIMMY", 1, 2, 3, "WOOF")
print(id(obj))
-
Esta terminología es incorrecta.
classmethod
s ystaticmethod
s son dos cosas diferentes.classmethod
apostarcls
mientrasstaticmethod
s no tiene ningún parámetro requerido.– wjandrea
15 de noviembre de 2022 a las 18:25
-
Además, no creo que este sea un buen ejemplo de un
classmethod
porque para que querrías unoCity
ejemplo para afectar a todos los demás? Como, ¿por qué elCity
clase incluso tiene uncountry
atributo en primer lugar? ¿No debería cada unoCity
instancia definir su propio país? Di que quería hacer unCity
instancia para Tokio y otra para Toronto; eso no es posible con esto, entonces, ¿cómo es útil? He aquí un mejor ejemplo, incluyendo unstaticmethod
.– wjandrea
15 de noviembre de 2022 a las 18:28
-
Gracias @wjandrea, no estoy 100% seguro de haber entendido tus comentarios y por qué mi respuesta está dando información incorrecta de alguna manera.
– RtmY
15/11/2022 a las 19:35
Manikandan Raju
Si desea llamar al método sin crear un objeto, puede cambiar el método a un método estático.
class MyClass:
@staticmethod
def method(arg):
print(arg)
MyClass.method("i am a static method")
Ese mensaje tiene innumerables causas; la razón específica aquí es que todos los métodos de instancia esperan un primer argumento que por costumbre llamamos
self
. Así declarandodef method(arg):
es incorrecto para un método, debería serdef method(self, arg):
. Cuando el método dispatch intenta llamarmethod(arg):
y unir dos parámetrosself, arg
en su contra, obtienes ese error.– smci
2 de mayo de 2020 a las 14:56