“TypeError: method () toma 1 argumento posicional pero se dieron 2” pero solo pasé uno

10 minutos de lectura

Avatar de usuario de Zero Piraeus
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?

  • 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í declarando def method(arg): es incorrecto para un método, debería ser def method(self, arg):. Cuando el método dispatch intenta llamar method(arg): y unir dos parámetros self, arg en su contra, obtienes ese error.

    – smci

    2 de mayo de 2020 a las 14:56

Avatar de usuario de Zero Piraeus
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 MyNewClassfunciona 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

avatar de usuario de simhumileco
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 para self 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 @classmethodsque toman cls como su primer parámetro, no self.

    – wjandrea

    15 de noviembre de 2022 a las 18:16

Avatar de usuario de Jonru
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


Avatar de usuario de Stanislav Pankevich
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 givenporque 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)

Avatar de usuario de RtmY
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 selfpero 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. classmethods y staticmethods son dos cosas diferentes. classmethodapostar cls mientras staticmethods 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 classmethodporque para que querrías uno City ejemplo para afectar a todos los demás? Como, ¿por qué el City clase incluso tiene un country atributo en primer lugar? ¿No debería cada uno City instancia definir su propio país? Di que quería hacer un City instancia para Tokio y otra para Toronto; eso no es posible con esto, entonces, ¿cómo es útil? He aquí un mejor ejemplo, incluyendo un staticmethod.

    – 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

avatar de usuario de wjandrea
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. classmethods y staticmethods son dos cosas diferentes. classmethodapostar cls mientras staticmethods 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 classmethodporque para que querrías uno City ejemplo para afectar a todos los demás? Como, ¿por qué el City clase incluso tiene un country atributo en primer lugar? ¿No debería cada uno City instancia definir su propio país? Di que quería hacer un City instancia para Tokio y otra para Toronto; eso no es posible con esto, entonces, ¿cómo es útil? He aquí un mejor ejemplo, incluyendo un staticmethod.

    – 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

Avatar de usuario de Manikandan Raju
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")

¿Ha sido útil esta solución?