TypeError: method () akzeptiert 1 Positionsargument, aber 2 wurden angegeben


269

Wenn ich eine Klasse habe ...

class MyClass:

    def method(arg):
        print(arg)

... mit dem ich ein Objekt erstelle ...

my_object = MyClass()

... auf die ich so nenne 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)

... warum sagt mir Python, dass ich zwei Argumente gegeben habe, obwohl ich nur eines gegeben habe?


Diese Nachricht hat unzählige Ursachen. Der spezifische Grund hierfür ist, dass alle Instanzmethoden ein erstes Argument erwarten, das wir benutzerdefiniert aufrufen self. Das Deklarieren def method(arg):ist für eine Methode falsch, sollte es auch sein def method(self, arg):. Wenn der Methodenversand versucht, method(arg):zwei Parameter aufzurufen und abzugleichen self, arg, wird dieser Fehler angezeigt.
smci

Antworten:


365

In Python gilt Folgendes:

my_object.method("foo")

... ist syntaktischer Zucker , den der Dolmetscher hinter den Kulissen übersetzt in:

MyClass.method(my_object, "foo")

... was, wie Sie sehen, tatsächlich zwei Argumente hat - es ist nur so, dass das erste aus Sicht des Anrufers implizit ist.

Dies liegt daran, dass die meisten Methoden mit dem Objekt arbeiten, für das sie aufgerufen werden. Daher muss es eine Möglichkeit geben, auf dieses Objekt innerhalb der Methode zu verweisen. Konventionell wird dieses erste Argument selfinnerhalb der Methodendefinition aufgerufen :

class MyNewClass:

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

Wenn Sie method("foo")eine Instanz von aufrufen MyNewClass, funktioniert dies wie erwartet:

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

Gelegentlich (aber nicht oft) interessiert Sie das Objekt, an das Ihre Methode gebunden ist , wirklich nicht , und unter diesen Umständen können Sie die Methode mit der integrierten Funktion dekorieren , um Folgendes staticmethod()zu sagen:

class MyOtherClass:

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

... in diesem Fall müssen Sie selfder Methodendefinition kein Argument hinzufügen , und es funktioniert immer noch:

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

97
Kurz gesagt: Das Hinzufügen selfals erstes Argument zur Methode löst das Problem.
Amöbe

@amoebe - meine Art von Person
Carlos

20

Noch etwas zu beachten, wenn diese Art von Fehler auftritt:

Ich bin auf diese Fehlermeldung gestoßen und fand diesen Beitrag hilfreich. Es stellte sich heraus, dass ich in meinem Fall eine __init__()Objektvererbung überschrieben hatte .

Das geerbte Beispiel ist ziemlich lang, daher gehe ich zu einem einfacheren Beispiel über, bei dem keine Vererbung verwendet wird:

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

Ergebnis ist:

<__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 hat diesen Tippfehler nicht verstanden. Notepad ++ auch nicht (andere Editoren / IDEs könnten).

Zugegeben, dies ist ein TypeError "nimmt keine Parameter". Er unterscheidet sich in Bezug auf die Objektinitialisierung in Python nicht wesentlich von "got two", wenn man einen erwartet.

Adressierung des Themas: Ein Überladungsinitialisierer wird verwendet, wenn er syntaktisch korrekt ist. Andernfalls wird er ignoriert und stattdessen der integrierte Initialisierer verwendet. Das Objekt wird dies nicht erwarten / behandeln und der Fehler wird ausgelöst.

Im Fall des Sytax-Fehlers: Das Update ist einfach. Bearbeiten Sie einfach die benutzerdefinierte init-Anweisung:

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

1
Hier gibt es keine SyntaxError. Der Code ist syntaktisch korrekt. Es definiert nur korrekt eine Methode mit dem Namen ___init__, die niemand jemals aufrufen wird, anstelle der speziellen Methode __init__. Aus diesem Grund wird kein Fehler erkannt, da kein Fehler erkannt werden kann.
Abarnert

14

In einfachen Worten.

In Python sollten Sie selfallen definierten Methoden in Klassen Argumente als erstes Argument hinzufügen :

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

Dann können Sie Ihre Methode entsprechend Ihrer Intuition anwenden:

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

Dies sollte dein Problem lösen :)

Zum besseren Verständnis können Sie auch die Antworten auf diese Frage lesen: Was ist der Zweck des Selbst?


2
Was ist los mit dieser Antwort? Warum hat ihr jemand einen negativen Punkt gegeben? Immerhin ist es die Antwort auf die Frage und zeichnet sich durch ihre Einfachheit im Vergleich zu anderen Antworten aus, was für einige Leute wichtig sein kann, die nach einer Antwort suchen. Ist es nicht?
Simhumileco

10

Als Python-Neuling hatte ich dieses Problem, als ich die Python- **Funktion falsch verwendete. Der Versuch, diese Definition von irgendwoher aufzurufen:

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

Die Verwendung eines Anrufs ohne Doppelstern verursachte das Problem:

self.create_properties_frame(frame, kw_gsp)

TypeError: create_properties_frame () akzeptiert 2 Positionsargumente, aber 3 wurden angegeben

Die Lösung besteht darin **, dem Argument Folgendes hinzuzufügen :

self.create_properties_frame(frame, **kw_gsp)

1
Ich komme aus JavaScript und erwarte, eine Liste oder ein Wörterbuch als Argument übergeben zu können. Aber anscheinend funktioniert Python nicht so: Sie müssen die Liste mit * oder ** zerstören, wobei letzteres für eine Liste mit Schlüsselwörtern gilt.
Little Brain

1
@LittleBrain: Ja, Sie können eine Liste (oder ein Diktat) übergeben, wenn Sie möchten, dass sie innerhalb der Funktion als Liste (/ dict) behandelt werden. Wenn Sie jedoch möchten, dass die einzelnen Werte entpackt und mit den Argumenten (/ kwargs) in der Funktion abgeglichen werden, benötigen Sie die Syntax *args(/ **kwargs).
smci

9

Es tritt auf, wenn Sie nicht die Anzahl der Parameter angeben, nach denen die __init__()oder eine andere Methode sucht.

Beispielsweise:

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

Wenn Sie das obige Programm ausführen, wird folgende Fehlermeldung angezeigt:

TypeError: __init __ () verwendet 1 Positionsargument, aber 6 wurden angegeben

Wie können wir dieses Ding loswerden?

Übergeben Sie einfach die Parameter, nach welcher __init__()Methode gesucht wird

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

Sie sollten tatsächlich eine Klasse erstellen:

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

0

In meinem Fall habe ich vergessen, das hinzuzufügen ()

Ich habe die Methode so aufgerufen

obj = className.myMethod

Aber es sollte so sein

obj = className.myMethod()

-1

Übergeben Sie den clsParameter @classmethodan, um dieses Problem zu beheben.

@classmethod
def test(cls):
    return ''
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.