ТипError: метод() принимает 1 позиционный аргумент, но 2 даны

Если у меня есть класс...

class MyClass:

    def method(arg):
        print(arg)

... который я использую для создания объекта...

my_object = MyClass()

... на котором я называю method("foo") так...

>>> my_object.method("foo")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: method() takes exactly 1 positional argument (2 given)

... почему Python говорит мне, что я дал ему два аргумента, когда я только дал один?

Ответ 1

В Python это:

my_object.method("foo")

... является синтаксическим сахаром, который интерпретатор переводит за кулисами в:

MyClass.method(my_object, "foo")

... который, как вы можете видеть, действительно имеет два аргумента - это просто, что первый из них неявный, с точки зрения вызывающего.

Это связано с тем, что большинство методов выполняют некоторую работу с объектом, на который они вызваны, поэтому для этого объекта должен быть какой-то способ, который должен быть указан внутри метода. По соглашению этот первый аргумент называется self внутри определения метода:

class MyNewClass:

    def method(self, arg):
        print(self)
        print(arg)

Если вы вызываете method("foo") в экземпляре MyNewClass, он работает как ожидалось:

>>> my_new_object = MyNewClass()
>>> my_new_object.method("foo")
<__main__.MyNewClass object at 0x29045d0>
foo

Иногда (но не часто) вам действительно не нужен объект, к которому привязан ваш метод, и в этом случае вы можете украсить метод с встроенной функцией staticmethod(), чтобы сказать так:

class MyOtherClass:

    @staticmethod
    def method(arg):
        print(arg)

... в этом случае вам не нужно добавлять аргумент self к определению метода, и он все еще работает:

>>> my_other_object = MyOtherClass()
>>> my_other_object.method("foo")
foo

Ответ 2

Что-то еще нужно учитывать при возникновении такого типа ошибки:

Я столкнулся с этим сообщением об ошибке и нашел это сообщение полезным. Оказывается, в моем случае я переопределил init(), где было наследование объектов.

Унаследованный пример довольно длинный, поэтому я перейду к более простому примеру, который не использует наследование:

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")

Результат:

<__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 не заметил эту опечатку. Также Notepad ++ (другие редакторы /IDE могли бы).

Конечно, это "не принимает параметров" TypeError, он не сильно отличается от "получил два" при ожидании одного, в терминах инициализации объекта в Python.

Адресация темы: инициализатор перегрузки будет использоваться, если синтаксически правильно, но если он не будет проигнорирован и вместо него будет использоваться встроенный. Объект не будет ожидать/обрабатывать это, и ошибка будет сброшена.

В случае ошибки sytax: исправление простое, просто отредактируйте пользовательский оператор init:

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

Ответ 3

Это происходит, когда вы не указываете число параметров, которое ищет __init__() или любой другой метод.

Например:

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")

Когда вы запускаете вышеуказанную программу, она выдает такую ошибку:

TypeError: __init__() takes 1 positional argument but 6 were given

Как мы можем избавиться от этой вещи?

Просто передайте параметры, что ищет метод __init__()

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))

Ответ 4

Новичок в Python, у меня была эта проблема, когда я неправильно использовал функцию Python **. Попытка вызвать это определение откуда-то:

def create_properties_frame(self, parent, **kwargs):

проблема с вызовом без двойной звезды:

self.create_properties_frame(frame, kw_gsp)

TypeError: create_properties_frame() takes 2 positional arguments but 3 were given

Решение состоит в том, чтобы добавить ** к аргументу:

self.create_properties_frame(frame, **kw_gsp)

Ответ 5

Простыми словами.

В Python вы должны добавить аргумент self в качестве первого аргумента для всех определенных методов в классах:

class MyClass:
  def method(self, arg):
    print(arg)

Тогда вы можете использовать свой метод в соответствии с вашей интуицией:

>>> my_object = MyClass()
>>> my_object.method("foo")
foo

Это должно решить вашу проблему :)

Для лучшего понимания вы также можете прочитать ответы на этот вопрос: какова цель самого себя?

Ответ 6

Передайте параметр cls в @classmethod чтобы решить эту проблему.

@classmethod
def test(cls):
    return ''