TypeError: method () бере 1 позиційний аргумент, але 2 було надано


270

Якщо у мене клас ...

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 каже мені, що я дав два аргументи, коли я дав лише один?


Це повідомлення має незрозумілі причини; конкретна причина тут полягає в тому, що всі методи екземпляра очікують першого аргументу, який ми звичаєм називаємо self. Отже, декларування def method(arg):є неправильним для методу, воно повинно бути def method(self, arg):. Коли диспетчер методу намагається викликати method(arg):і співставити два параметри self, argпроти нього, ви отримуєте цю помилку.
smci

Відповіді:


367

У 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

99
Якщо коротко: додавання selfв якості першого аргументу методу вирішує проблему.
амебе

@amoebe - мій тип людини
Карлос

21

Ще щось, що слід враховувати, коли виникає такий тип помилок:

Я зіткнувся з цим повідомленням про помилку і вважав цю публікацію корисною. Виявляється, в моєму випадку я змінив місце, __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 не вловив цю помилку. Також Блокнот ++ (інші редактори / IDE не могли).

Зрозуміло, що це "не приймає параметрів" TypeError, він не сильно відрізняється, ніж "отримав два", коли очікує одного, з точки зору ініціалізації об'єкта в Python.

Звернення до теми: Якщо синтаксично правильно, буде використаний ініціалізатор перевантаження, але якщо ні, то він буде ігнорований, а замість цього вбудований. Об'єкт цього не очікує / не впорається, і помилка викидається.

У випадку помилки синтаксису: виправлення просте, просто відредагуйте спеціальний оператор init:

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

1
Тут немає SyntaxError. Код синтаксично правильний; він просто правильно визначає метод, названий ___init__, який ніхто ніколи не збирається називати, а не спеціальний метод __init__. Ось чому не виявлено жодної помилки - тому що її немає для виявлення.
abarnert

14

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

У Python слід додати selfаргумент як перший аргумент до всіх визначених методів у класах:

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

Тоді ви можете використовувати свій метод відповідно до своєї інтуїції:

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

Це має вирішити вашу проблему :)

Для кращого розуміння ви також можете прочитати відповіді на це питання: Яка мета себе?


2
Що не так у цій відповіді? Чому хтось поставив їй негативну точку? Адже саме відповідь на питання і відрізняється своєю простотою порівняно з іншими відповідями, що може бути важливо для деяких людей, які шукають відповідь. Чи не так?
simhumileco

10

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

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

використання дзвінка без подвійної зірки спричинило проблему:

self.create_properties_frame(frame, kw_gsp)

TypeError: create_properties_frame () бере 2 позиційні аргументи, але 3 було надано

Рішення полягає в додаванні **до аргументу:

self.create_properties_frame(frame, **kw_gsp)

1
Виходячи з JavaScript, я очікую, що зможу передати список або словник як аргумент. Але схоже, що так не працює Python: вам слід деструктурувати список за допомогою * або **, останнє - для списку аргументів ключових слів.
Маленький мозок

1
@LittleBrain: так, ви можете передати список (або диктат), якщо ви хочете, щоб вони розглядалися як список (/ dict) всередині функції. Але якщо ви хочете, щоб їхні індивідуальні значення розпаковувались і відповідали аргам (/ kwargs) у функції, тоді вам потрібен синтаксис *args(/ **kwargs).
smci

9

Він виникає, коли ви не вказуєте значення no __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 __ () бере 1 позиційний аргумент, але 6 було надано

Як ми можемо позбутися цієї речі?

Просто передайте параметри, який __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))

1

Ви насправді повинні створити клас:

class accum:
    def __init__(self):
        self.acc = 0
    def accumulator(self, var2add, end):
        if not end:
            self.acc+=var2add
    return self.acc

0

У моєму випадку я забув додати ()

Я називав метод таким

obj = className.myMethod

Але воно має бути таким

obj = className.myMethod()

-1

Введіть clsпараметр у, @classmethodщоб вирішити цю проблему.

@classmethod
def test(cls):
    return ''
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.