511 Stimmen

"TypeError: method() erwartet 1 Positionales Argument, aber es wurden 2 übergeben." aber ich habe nur eins übergeben.

Wenn ich eine Klasse habe ...

class MyClass:

    def method(arg):
        print(arg)

... mit der ich ein Objekt erstelle ...

my_object = MyClass()

... auf das ich method("foo") wie folgt aufrufe ...

>>> my_object.method("foo")
Traceback (most recent call last):
  File "", line 1, in 
TypeError: method() nimmt genau 1 Positional-Argument an (2 gegeben)

... warum sagt mir Python, dass ich ihm zwei Argumente gegeben habe, wenn ich nur eins gegeben habe?

635voto

Zero Piraeus Punkte 52970

In Python, this:

my_object.method("foo")

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

MyClass.method(my_object, "foo")

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

Dies liegt daran, dass die meisten Methoden etwas mit dem Objekt tun, auf dem sie aufgerufen werden. Daher muss es eine Möglichkeit geben, dass auf das Objekt innerhalb der Methode verwiesen wird. Nach Konvention wird dieses erste Argument innerhalb der Methodendefinition self genannt:

class MyNewClass:

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

Wenn Sie method("foo") an einer Instanz von MyNewClass aufrufen, funktioniert es wie erwartet:

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

Gelegentlich (aber nicht oft) ist es Ihnen wirklich egal, an welches Objekt Ihre Methode gebunden ist, und in diesem Fall können Sie die Methode mit der integrierten decorate Funktion mit der integrierten methode dekorieren, um dies zu kennzeichnen:

class MyOtherClass:

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

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

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

49voto

simhumileco Punkte 26451

In einfachen Worten

In Python sollten Sie self als ersten Parameter zu allen definierten Methoden in Klassen hinzufügen:

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

Dann können Sie Ihre Methode nach Ihrem eigenen Ermessen verwenden:

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

Zur besseren Verständnis können Sie auch die Antworten auf diese Frage lesen: Was ist der Zweck von self?

25voto

Jonru Punkte 374

Etwas anderes, was man beachten sollte, wenn dieser Typ des Fehlers auftritt:

Ich bin auf diese Fehlermeldung gestoßen und fand diesen Beitrag hilfreich. Es stellte sich heraus, dass ich in meinem Fall ein __init__() überschrieben hatte, wo es Vererbung von Objekten gab.

Das vererbte Beispiel ist ziemlich lang, deshalb werde ich zu einem einfacheren Beispiel überspringen, das keine Vererbung verwendet:

class MyBadInitClass:
    def ___init__(self, name):
        self.name = name

    def name_foo(self, arg):
        print(self)
        print(arg)
        print("Mein Name ist", 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>
NeuFoo
Traceback (most recent call last):
  File "C:/Users/Orange/PycharmProjects/Chapter9/bad_init_example.py", line 41, in 
    my_bad_init_object = MyBadInitClass(name="Test Name")
TypeError: object() takes no parameters

PyCharm hat diesen Tippfehler nicht erkannt. Auch Notepad++ nicht (andere Editoren/IDEs könnten es).

Zugegeben, dies ist ein "takes no parameters" TypeError, es unterscheidet sich nicht viel von "got two", wenn man nur einen erwartet, in Bezug auf die Objektinitialisierung in Python.

Zum Thema: Ein überladener Initialisierer wird verwendet, wenn er syntaktisch korrekt ist, ansonsten wird er ignoriert und stattdessen der eingebaute verwendet. Das Objekt erwartet/damit umgeht und der Fehler wird ausgelöst.

Im Fall des Syntaxfehlers: Die Lösung ist einfach, bearbeiten Sie einfach die benutzerdefinierte Init-Anweisung:

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

21voto

Stanislav Pankevich Punkte 10368

Dieses Problem kann auch durch das Versäumnis verursacht werden, Schlüsselwortargumente ordnungsgemäß an eine Funktion zu übergeben.

Zum Beispiel, gegeben eine definierte Methode wie:

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

ein Aufruf wie dieser:

self.create_properties_frame(frame, kw_gsp)

wird den Fehler TypeError: create_properties_frame() benötigt 2 Positional-Argumente, aber es wurden 3 übergeben verursachen, da das kw_gsp-Dictionary als Positional-Argument behandelt wird anstatt in separate Schlüsselwortargumente aufgeteilt zu werden.

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

self.create_properties_frame(frame, **kw_gsp)

15voto

RtmY Punkte 11910

Wie in anderen Antworten erwähnt - wenn Sie eine Instanzmethode verwenden, müssen Sie self als ersten Argument übergeben - dies ist die Ursache des Fehlers.

Zusätzlich dazu ist es wichtig zu verstehen, dass nur Instanzmethoden self als ersten Argument benötigen, um auf die Instanz zu verweisen.

Falls die Methode Statisch ist, übergeben Sie nicht self, sondern stattdessen ein cls-Argument (oder class_).

Bitte sehen Sie ein Beispiel unten.

class City:

   country = "USA" # Dies ist ein Klassenattribut, das über alle Instanzen hinweg gemeinsam genutzt wird  (und nicht pro Instanz erstellt wird)

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

   # Dies ist eine Instanzmethode, die self als ersten Argument benötigt, um auf die Instanz zu verweisen 
   def print_population(self, some_nice_sentence_prefix):
       print(some_nice_sentence_prefix +" In " +self.name + " leben " +self.population + " Menschen!")

   # Dies ist eine statische (Klassen-)Methode, die mit dem @classmethod-Attribut markiert ist
   # Alle Klassenmethoden müssen ein Klassenargument als ersten Parameter enthalten. Die Konvention ist es "cls" zu nennen, aber class_ ist auch in Ordnung
   @classmethod
   def change_country(cls, new_country):
       cls.country = new_country

Einige Tests nur um die Dinge klarer zu machen:

# Objekte bevölkern
city1 = City("New York",    "Ost", "18.804.000")
city2 = City("Los Angeles", "West", "10.118.800")

#1) Verwendung der Instanzmethode: Es ist nicht erforderlich, "self" zu übergeben - es wird als Instanz city1 übergeben
city1.print_population("Wussten Sie schon?") # Gibt aus: Wussten Sie schon? In New York leben 18.804.000 Menschen!

#2.A) Verwendung der statischen Methode im Objekt
city2.change_country("Kanada")

#2.B) Wird in allen Objekten reflektiert
print("city1.country=",city1.country) # Gibt Kanada aus
print("city2.country=",city2.country) # Gibt Kanada aus

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X